可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am writing a program which write statistical tests in Delphi (must be Delphi) and I've heard that the Random functionality is somewhat odd. You have to call randomize to randomize the seed of the random function when the program starts.
I'm wondering if the random function (after calling randomize) is random enough for statistical tests or a Mersenne twister is needed? Does anyone have any insight into random's actual implementation which can tell me how important this is?
回答1:
Whether Random
is sufficiently reliable for your statistical tests will depend on the context in which you intend to use it.
Having said that, I have written several pieces of Delphi code that need to do proper statistics, and have used Random
e.g. for obtaining various null distributions, data pseudo-replications and resamplings. So far, I have not come across any case in my own code where Random
would have yielded biased or unreliable results, or results which would have precluded its use for the intended statistical test. But what holds for my code does not necessarily have to hold for yours.
If in doubt, you could of course statistically analyse the results of calls to Random
(e.g. in R, SPSS, etc.) and examine whether the distribution of results violate the distributional requirements for your particular statistical test(s). [If you're a proper scientist, this is what you should do anyway.]
Should you need other PRNGs - e.g. the TPMath library contains some. (For more involved things, there's also the option of calling elaborate statistical functions from R via Delphi.)
回答2:
Delphi's PRNG, like almost all programming language RTL PRNGs, is a linear congruential generator.
It's good enough for most small-scale things, but there are things to watch out for. In particular, watch out for low-order bits: the pattern of multiplication and add means that low-order bits are not very random at all. But this generally only applies to large 32-bit values pulled out and then truncated with mod
or similar. Using Random(10)
to pluck a value between 0 and 9 internally uses a multiplication over the whole 32-bit range rather than a mod
operation.
回答3:
I couldn't resist.
回答4:
If you are seeking a way to guarantee uniqueness of random numbers with the fastest execution time, About.com has created a challenge on Fastest Unique Random Number Generator, and Patrick van Logchem's implementation has been elected as the winner.
回答5:
Unless you buy some relatively esoteric hardware, the best approximation to random numbers a computer can provide is a completely deterministic pseudorandom sequence. In general, the randomize function uses some relatively random value (often based on the time, but sometimes on mouse movements - I have no idea what Delphi does) as a seed which provides the entry point to the pseudorandom sequence. Without this, you will end up getting back the same set of random numbers in the same order each time, which tends to defeat the purpose of using random numbers in the first place.
Okay, I realize that this doesn't answer the question about reliability, but it should give you some confidence that requiring you to call randomize is a sign of a good generator rather than of a bad one. There are a bunch of statistical tests which show how random a sequence of numbers is, and it is likely that the Delphi random number generator is suitable for many purposes as it is a mature product.
回答6:
Just to add to the pool of possibilities - Windows offers a range of built-in Cryptography functions. There probably is a Delphi wrapper for them as well, if it's not already included by default.
Among these functions is also a cryptographically strong random number generator. This is by far the best randomness you will get in software, because it seeds itself based on a very long list of factors. I'm not sure, but I suspect it will even use a hardware random number generator if you have one.
And if that's not enough, you can also try to sign up at the Quantum Random Bit Generator Service for some REALLY random values.
回答7:
From the Embarcadero web site:
_lrand is the long random number generator function. _rand uses a multiplicative congruential random number generator with period 2^64 to return successive pseudo-random numbers in the range from 0 to 2^31 - 1.
The generator is reinitialized by calling srand with an argument value of 1. It can be set to a new starting point by calling srand with a given seed number.
回答8:
If they didn't change the implementation since I analyzed it(Delphi 4 IIRC), the Delphi PRNG is implemented like this:
Randseed:=int32(Randseed*$08088405)+1
result:=Randseed*Range shr 32
(Pseudocode/assume the multiplications are on arbitrarily large integers)
回答9:
Return random between 0..9
StrToInt(copy(FloatToStr(Random),4,1))
Note:Check FloatToStr(Random) length before use or use any other digit from the decimal part...