根据getNext模块中PCGRandom的手册页,我们可以生成给定范围内的随机数,例如:
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
在这里,我注意到手册页针对整数和实数情况给出了以下注释:
对于整数,此类使用一种策略来生成未经过严格研究且可能存在统计问题的特定范围内的值。
对于实数,此类通过计算[0,1]中的随机值并缩放和移动该值来生成[max,min]中的随机值。请注意,不是间隔[min,max]中所有可能的浮点值都可以以此方式构造。
(在这里我用斜体字强调)。对于实数,这与所谓的“浮点数密度”有关,例如this page中问)?另外,对于整数,是否存在某些情况,即使是“典型”使用,也需要注意吗? (此处的“典型”是指,例如,在给定范围内大致平坦分布的10 ** 8个随机整数的生成。)
仅供参考,我的“用例”不是像对随机数进行严格的质量测试那样,而是典型的蒙特卡洛计算(例如,选择立方晶格上的随机位置)。
答案 0 :(得分:3)
手册页中的注释表明与已研究的其他PCG随机数方法(至少由PCG算法的作者)有所不同。
浮点数的问题确实与浮点数密度有关。请参阅PCG作者的http://www.pcg-random.org/using-pcg-c-basic.html#generating-doubles。即使在[0.0,1.0]中生成随机数,这也是一个潜在的问题。文档中的这一段描述了该问题:
当生成实数,虚数或复数时, 实现使用生成64位无符号的策略 整数,然后乘以2.0 **-64以将其转换为 浮点数。虽然这确实构成了统一 圆角浮点值的分布,它省去了很多 可能的实际值(例如2 **-128)。我们相信 策略具有合理的统计属性。的副作用 这种策略是可以生成实数1.0,因为 四舍五入。因为PCG可以产生实数,所以可以产生0.0 值0为随机整数。
请注意,64位实数可以存储小至2.0**-1024
的数字,但是用正整数除以2**64
来获得这样的数字是完全不可能的。 (在这里和上面,我使用**
作为指数运算符,因为这就是Chapel语法中的功能)。我建议阅读IEEE浮点格式(例如https://en.wikipedia.org/wiki/IEEE_754或https://en.wikipedia.org/wiki/Double-precision_floating-point_format)以获取该区域的背景信息。如果您正在使用RNG为针对real(64)
值的算法生成测试输入,则可能会对此感到担心。在这种情况下,您可能甚至希望生成很小的值。请注意,尽管构造一个可以以非均匀方式生成所有real(64)
值的RNG并不是那么困难(例如,只需将uint
中的位复制到real
中)。 / p>
关于您问题的另一部分:
我使用TestU01对特定范围内的随机整数的生成进行了一些基本的统计测试,并且我对在蒙特卡洛计算中使用它很有信心。但是,我不是这方面的专家,因此我在文档中添加了该警告。文档中的以下信息描述了我所做的测试:
我们已经用TestU01测试了此实现(可从以下网址获得: http://simul.iro.umontreal.ca/testu01/tu01.html)。我们测量了 用TestU01 1.2.3和Crush套件实现 144个统计测试。结果是:
- 生成统一实数没有失败
- 1个生成32位值的失败(对于具有相同配置的PCG参考版本也是如此)
生成64位值的- 0次失败(我们将其作为2提供给TestU01 不同的32位值,因为它一次只能接受32位)
产生有界整数的- 0次失败(我们通过向
[0..,2**31+2**30+1)
请求值,直到我们拥有两个<2 ** 31的值,删除了前0位,然后将前16位组合到值提供给TestU01)。