生成给定范围内的随机整数和实数

Generating random integer and real numbers in a given range

根据getNext in the PCGRandom模块的man page,我们可以生成给定范围内的随机数,例如:

use Random;

var rng1 = new owned RandomStream( eltType= real, seed= 100 );
var rng2 = new owned RandomStream( eltType= int,  seed= 100 );

for i in 1..5 do
    writeln( rng1.getNext( min= 3.0, max= 5.0 ) );

writeln();
for i in 1..5 do
    writeln( rng2.getNext( min= 20, max= 80 ) );

给出(使用 chpl-1.20.0):

4.50371
4.85573
4.2246
4.84289
3.63607

36
57
79
39
57

在这里,我注意到手册页针对整数和实数情况给出了以下注释:

For integers, this class uses a strategy for generating a value in a particular range that has not been subject to rigorous study and may have statistical problems.

For real numbers, this class generates a random value in [max, min] by computing a random value in [0,1] and scaling and shifting that value. Note that not all possible floating point values in the interval [min, max] can be constructed in this way.

(我用斜体来强调)。对于实数,这是否与所谓的“浮点数密度”有关,例如在 this page 中询问)?此外,对于整数,是否存在某些情况,即使是“典型”用途,我们也需要小心? (这里,“典型”是指,例如,在给定范围内大致平坦分布的 10**8 个随机整数的生成。)

仅供参考,我的“用例”不是随机数的严格质量测试,而是典型的 Monte Carlo 计算(例如,在立方晶格上选择随机位置)。

手册页中的注释指出了与已研究过的其他 PCG 随机数方法(至少由 PCG 算法的作者研究过)的不同之处。

浮点数的问题确实与浮点数密度有关。请参阅 PCG 作者的 http://www.pcg-random.org/using-pcg-c-basic.html#generating-doubles。即使在 [0.0, 1.0] 中生成随机数,这也是一个潜在的问题。文档中的这一段描述了这个问题:

When generating a real, imaginary, or complex number, this implementation uses the strategy of generating a 64-bit unsigned integer and then multiplying it by 2.0**-64 in order to convert it to a floating point number. While this does construct a uniform distribution on rounded floating point values, it leaves out many possible real values (for example, 2**-128). We believe that this strategy has reasonable statistical properties. One side effect of this strategy is that the real number 1.0 can be generated because of rounding. The real number 0.0 can be generated because PCG can produce the value 0 as a random integer.

请注意,64 位实数可以存储小至 2.0**-1024 的数字,但通过将正整数除以 2**64 来获得这样的数字是非常不可能的。 (这里和上面我使用 ** 作为求幂运算符,因为它在 Chapel 语法中就是这样做的)。我建议阅读 IEEE 浮点格式(例如 https://en.wikipedia.org/wiki/IEEE_754 or https://en.wikipedia.org/wiki/Double-precision_floating-point_format )以获取该领域的背景信息。如果您使用 RNG 为基于 real(64) 值运行的算法生成测试输入,您可能会关心这一点。在那种情况下,您可能希望生成非常小的值。请注意,构建一个可以以非统一方式生成所有 real(64) 值的 RNG 并不难(例如,只需将位从 uint 复制到 real)。

关于你问题的另一部分:

我用 TestU01 生成特定范围内的随机整数进行了一些基本的统计测试,我对它在 Monte Carlo 计算中的使用充满信心。但是我不是这方面的专家,因此我在文档中提出了警告。文档中的以下信息描述了我所做的测试:

We have tested this implementation with TestU01 (available at http://simul.iro.umontreal.ca/testu01/tu01.html ). We measured our implementation with TestU01 1.2.3 and the Crush suite, which consists of 144 statistical tests. The results were:

  • no failures for generating uniform reals
  • 1 failure for generating 32-bit values (which is also true for the reference version of PCG with the same configuration)
  • 0 failures for generating 64-bit values (which we provided to TestU01 as 2 different 32-bit values since it only accepts 32 bits at a time)
  • 0 failures for generating bounded integers (which we provided to TestU01 by requesting values in [0..,2**31+2**30+1) until we had two values < 2**31, removing the top 0 bit, and then combining the top 16 bits into the value provided to TestU01).