2008-08-08 50 views
17

Tôi biết rằng chỉ cần sử dụng rand() là có thể dự đoán được, nếu bạn biết mình đang làm gì và có quyền truy cập vào máy chủ.Tạo ngẫu nhiên tốt hơn PHP

Tôi có một dự án là cao phụ thuộc vào việc chọn số ngẫu nhiên không thể đoán trước nhất có thể. Vì vậy, tôi đang tìm kiếm các đề xuất, hoặc các hàm tích hợp hoặc chức năng người dùng khác, có thể tạo ra một số ngẫu nhiên tốt hơn.

Tôi sử dụng này để làm một chút thử nghiệm:

$i = 0; 

while($i < 10000){ 
    $rand = rand(0, 100); 

    if(!isset($array[$rand])){ 
     $array[$rand] = 1; 
    } else { 
     $array[$rand]++; 
    } 

    sort($array); 
    $i++; 
} 

Tôi tìm thấy kết quả được phân bố đều, và có một mô hình lẻ với số lần mỗi số được tạo ra.

+0

Có chức năng mới trong php7, [thực hiện chính xác những gì bạn cần] (http://stackoverflow.com/a/31444887/1090562). –

Trả lời

21

Thêm, nhân hoặc cắt ngắn nguồn ngẫu nhiên kém sẽ cho bạn kết quả ngẫu nhiên kém. Xem Introduction to Randomness and Random Numbers để được giải thích.

Bạn nói đúng về hàm PHP rand(). Xem hình thứ hai trên Statistical Analysis để có hình minh họa nổi bật. (Con số đầu tiên là nổi bật, nhưng nó được vẽ bởi Scott Adams, không được vẽ bằng rand()).

Một giải pháp là sử dụng bộ tạo ngẫu nhiên thực sự như random.org. Khác, nếu bạn đang trên Linux/BSD/etc. là sử dụng /dev/random. Nếu tính ngẫu nhiên là nhiệm vụ quan trọng, bạn sẽ phải sử dụng hardware random generator.

3

Biến thể trên @KG, sử dụng mili giây kể từ EPOCH làm hạt giống cho rand?

+0

Sooooo, với các máy tính đa lõi nhanh hiện nay, bạn có một cơ hội khá vững chắc khi sử dụng lại hạt giống, nhiều lần? Lá cờ đỏ khổng lồ - bạn đang phát minh lại một bánh xe hình vuông, thậm chí 'srand()' không có đối số nào làm một công việc tốt hơn ("ngẫu nhiên hơn"). – Piskvor

5

random.org có API bạn có thể truy cập qua HTTP.

RANDOM.ORG là dịch vụ số ngẫu nhiên thực sự tạo ngẫu nhiên qua tiếng ồn khí quyển.

4

Tôi sẽ cảnh giác với ấn tượng ngẫu nhiên: đã có nhiều thử nghiệm mà mọi người sẽ chọn phân phối ít ngẫu nhiên hơn. Có vẻ như tâm trí không giỏi trong việc sản xuất hay ước lượng sự ngẫu nhiên.

Có các bài viết hay về tính ngẫu nhiên tại Fourmilab, bao gồm một số khác true random generator. Có lẽ bạn có thể nhận được dữ liệu ngẫu nhiên từ cả hai trang web vì vậy nếu một trong những xuống bạn vẫn còn có khác.

Fourmilab cũng cung cấp số test program để kiểm tra tính ngẫu nhiên. Bạn có thể sử dụng nó để kiểm tra các chương trình myRand() khác nhau của bạn.

Đối với chương trình cuối cùng của bạn, nếu bạn tạo 10000 giá trị, tại sao bạn không chọn giá trị cuối cùng trong số 10 nghìn? Bạn tự giới hạn mình vào một tập hợp con. Ngoài ra, nó sẽ không hoạt động nếu $ min và $ max của bạn lớn hơn 10000.

Dù sao, sự ngẫu nhiên bạn cần phụ thuộc vào đơn đăng ký của bạn. rand() sẽ là OK cho một trò chơi trực tuyến, nhưng không OK cho mật mã (bất cứ điều gì không được kiểm tra kỹ lưỡng với các chương trình thống kê sẽ không phù hợp cho mật mã anyway). Bạn là thẩm phán!

2

Một cách khác để nhận số ngẫu nhiên, tương tự như khái niệm để nhận được UUID

Phiên bản PHP 5.3 trở lên

openssl_random_pseudo_bytes(...) 

Hoặc bạn có thể thử library sau sử dụng RFC4122

1

Một mới PHP7 có một chức năng thực hiện chính xác những gì bạn cần: nó tạo ra cryptographically secure pseudo-random integers.

int random_int (int $min , int $max) 

Tạo các số nguyên ngẫu nhiên mã hóa phù hợp để sử dụng trong đó các kết quả không thiên vị là rất quan trọng (tức là xáo trộn sàn Poker).

Để có giải thích chi tiết hơn về PRNG và CSPRNG (và sự khác biệt) cũng như lý do tại sao phương pháp tiếp cận ban đầu của bạn thực sự là ý tưởng tồi, vui lòng đọc another highly similar answer.

Các vấn đề liên quan