2010-10-15 33 views
12

Tôi đang viết một chương trình mà viết bài kiểm tra thống kê trong Delphi (phải là Delphi) và tôi đã nghe nói rằng các chức năng ngẫu nhiên là hơi kỳ lạ. Bạn phải gọi ngẫu nhiên để ngẫu nhiên hạt giống của hàm ngẫu nhiên khi chương trình bắt đầu.Làm thế nào đáng tin cậy là chức năng ngẫu nhiên trong Delphi

Tôi tự hỏi liệu chức năng ngẫu nhiên (sau khi gọi ngẫu nhiên) có đủ ngẫu nhiên cho các kiểm tra thống kê hoặc cần phải có một misterenne không? Có ai có bất kỳ cái nhìn sâu sắc vào thực hiện thực tế của ngẫu nhiên mà có thể cho tôi biết tầm quan trọng này là gì?

+4

Có để gieo rắc một hàm Randomizer là hoàn toàn không phổ biến - bạn phải làm điều tương tự với misterenne. –

+1

Và khả năng gieo hạt một hàm ngẫu nhiên, nó thường là một lợi ích lớn. Bằng cách sử dụng cùng một hạt giống, bạn có thể sao chép kết quả của mình, điều này có thể giúp ích rất nhiều, ví dụ như khi gỡ lỗi. –

+1

Có một cuộc thảo luận tuyệt vời về chủ đề này trong chương 6 của cuốn sách của Julian Bucknall "Tomes of Delphi: Thuật toán và cấu trúc dữ liệu" (www.boyet.com) –

Trả lời

6

Cho dù Random là đủ đáng tin cậy cho các kiểm tra thống kê của bạn sẽ phụ thuộc vào ngữ cảnh mà bạn dự định sử dụng nó.

Có nói rằng, tôi đã viết một số đoạn mã Delphi cần phải làm thống kê thích hợp và đã sử dụng Random ví dụ: để có được các bản phân phối null khác nhau, sao chép và sao chép dữ liệu giả. Cho đến nay, tôi đã không đi qua bất kỳ trường hợp nào trong mã của riêng tôi, nơi Random sẽ mang lại kết quả thiên vị hoặc không đáng tin cậy hoặc kết quả sẽ loại trừ việc sử dụng nó cho thử nghiệm thống kê dự định. Nhưng những gì giữ cho mã của tôi không nhất thiết phải giữ cho bạn. Nếu bạn nghi ngờ, bạn có thể phân tích thống kê kết quả cuộc gọi đến Random (ví dụ: trong R, SPSS, v.v.) và kiểm tra xem phân phối kết quả có vi phạm các yêu cầu phân phối cho (các) kiểm tra thống kê cụ thể của bạn hay không. [Nếu bạn là một nhà khoa học phù hợp, đây là những gì bạn nên làm anyway.]

Nếu bạn cần các PRNG khác - e.g. thư viện TPMath chứa một số thư viện. (Đối với những thứ tham gia nhiều hơn, cũng có tùy chọn gọi các chức năng thống kê công phu từ R qua Delphi.)

4

Trừ khi bạn mua một số phần cứng tương đối bí truyền, phép tính gần đúng nhất với số ngẫu nhiên mà máy tính có thể cung cấp là chuỗi giả ngẫu nhiên hoàn toàn xác định. Nói chung, hàm ngẫu nhiên sử dụng một số giá trị tương đối ngẫu nhiên (thường dựa trên thời gian, nhưng đôi khi chuyển động trên chuột - tôi không biết Delphi làm gì) như một hạt giống cung cấp điểm vào chuỗi giả ngẫu nhiên. Nếu không có điều này, bạn sẽ nhận được cùng một tập hợp các số ngẫu nhiên trong cùng một thứ tự mỗi lần, có xu hướng đánh bại mục đích của việc sử dụng số ngẫu nhiên ngay từ đầu. Được rồi, tôi nhận ra rằng điều này không trả lời câu hỏi về độ tin cậy, nhưng nó sẽ cho bạn một số sự tự tin rằng yêu cầu bạn gọi ngẫu nhiên là dấu hiệu của một máy phát điện tốt hơn là một máy phát điện xấu. Có một loạt các bài kiểm tra thống kê cho thấy ngẫu nhiên một chuỗi các số, và có khả năng trình tạo số ngẫu nhiên Delphi phù hợp với nhiều mục đích vì nó là một sản phẩm trưởng thành.

16

alt text

Tôi không thể cưỡng lại.

+2

Tôi thích sự hài hước. Nhưng nó ** phải ** là CW! –

+1

Không, không có CW, nó hoàn toàn minh họa rằng những gì chúng ta có thể cảm nhận là không ngẫu nhiên, thực sự có thể hoàn toàn ngẫu nhiên. Sau khi tất cả, ngẫu nhiên không phải là vắng mặt của một mô hình ... –

+1

Bất cứ lúc nào bạn cảm thấy nghiêng để đặt "Tôi không thể cưỡng lại" trong "câu trả lời" của bạn, bạn nên nghiêng để làm cho nó CW. Đó là vấn đề mức độ, nhưng trong trường hợp này không có câu trả lời trực tiếp cho OP. – Argalatyr

20

PRNG của Delphi, giống như hầu hết tất cả ngôn ngữ lập trình RTL PRNG, là linear congruential generator.

Đủ tốt cho hầu hết mọi thứ ở quy mô nhỏ, nhưng có những điều cần chú ý. Đặc biệt, hãy chú ý tới các bit có thứ tự thấp: mô hình phép nhân và phép cộng có nghĩa là các bit bậc thấp không phải là rất ngẫu nhiên chút nào. Nhưng điều này thường chỉ áp dụng cho các giá trị 32 bit lớn được rút ra và sau đó cắt ngắn với mod hoặc tương tự. Sử dụng Random(10) để lấy một giá trị từ 0 đến 9 trong nội bộ sử dụng phép nhân trên toàn bộ phạm vi 32 bit thay vì hoạt động mod.

2

Từ trang web Embarcadero:

_lrand là dài chức năng bộ tạo số ngẫu nhiên. _rand sử dụng bộ tạo số ngẫu nhiên cộng số nhân với khoảng thời gian 2^64 để trả về số ngẫu nhiên liên tiếp trong phạm vi từ 0 đến 2^31 - 1.

Máy phát điện được khởi động lại bằng cách gọi srand với giá trị đối số là 1. Nó có thể được thiết lập để một điểm khởi đầu mới bằng cách gọi srand với một số hạt giống nhất định.

2

Nếu họ không thay đổi việc thực hiện kể từ khi tôi đã phân tích nó (Delphi 4 IIRC), Delphi PRNG được thực hiện như thế này:

Randseed:=int32(Randseed*$08088405)+1 
result:=Randseed*Range shr 32 

(Mã giả/giả định các phép nhân đang trên số nguyên tùy tiện lớn)

3

Chỉ cần thêm vào nhóm các khả năng - Windows cung cấp một loạt các built-in Cryptography functions. Có lẽ là một wrapper Delphi cho họ là tốt, nếu nó chưa được bao gồm theo mặc định.

Trong số các chức năng này cũng là cryptographically strong random number generator. Điều này là cho đến nay sự ngẫu nhiên tốt nhất bạn sẽ nhận được trong phần mềm, bởi vì nó hạt giống chính nó dựa trên một danh sách rất dài các yếu tố. Tôi không chắc chắn, nhưng tôi nghi ngờ nó thậm chí sẽ sử dụng một bộ tạo số ngẫu nhiên phần cứng nếu bạn có.

Và nếu điều đó là không đủ, bạn cũng có thể thử đăng ký tại Quantum Random Bit Generator Service đối với một số REALLY giá trị ngẫu nhiên.

-1

Return ngẫu nhiên giữa 0..9

StrToInt(copy(FloatToStr(Random),4,1)) 

Lưu ý: Kiểm tra FloatToStr chiều dài (Random) trước khi sử dụng hoặc sử dụng bất kỳ chữ số khác từ phần thập phân ...

+1

Cuộc gọi được đề nghị để tạo một số nguyên ngẫu nhiên trong khoảng 0 đến 9 là "ngẫu nhiên (10)" Sử dụng floattostr là thông minh, nhưng biểu thức được đưa ra đôi khi sẽ thất bại. Hãy xem xét: "randseed: = -1498392781; X: = StrToInt (sao chép (FloatToStr (Ngẫu nhiên), 4,1));" Trong trường hợp này ngẫu nhiên sẽ trả về chính xác 0,5, floattostr sẽ trả về "0,5", vì không có ký tự thứ tư, bản sao sẽ trả về chuỗi rỗng, và StrToInt sẽ thất bại với một ngoại lệ. –

+0

Ý tưởng là đưa ra ví dụ với sự phân tán lớn hơn (xem [link] (http://stackoverflow.com/a/3947122/636542)). Bạn có thể tự do nâng cao thuật toán này theo nhu cầu của bạn ... – DejanR

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