我目前的做法不足
现在,对于常规的整数我通常会写一些类似int rand 500;并完成它.
但是对于大整数,看起来兰德并不是为了这个.
使用以下代码,我运行了一个模拟200万次调用rand $bigint:
$perl -Mbigint -E 'say int rand 1230138339199329632554990773929330319360000000 for 1 .. 2e6' > rand.txt
所得集合的分布是不可取的:
> 0(56计数)
> 1e 040(112个计数)
> 1e 041(1411计数)
> 1e 042(14496计数)
> 1e 043(146324计数)
> 1e 044(1463824)
> 1e 045(373777个)
所以这个过程从来没有能够选择像999或5e 020这样的数字,这使得这种方法不适合我想要做的.
看起来这与rand的任意精度有关,在我的测试过程中,这并不会超过15位数:
$perl -E 'printf "%.66g",rand' 0.307037353515625
如何克服这个限制?
我最初的想法是,也许有一种方法可以影响兰特的精度,但感觉像是一个更大的问题的援助(即无法处理大整数).
无论如何,我希望有人以前走过这条路,知道如何纠正这种情况.
解决方法
一个更理论驱动的方法是使用多个呼叫到PRNG来创建足够的随机位,以便您的号码进行采样.必须小心,如果一些PRNG产生的位数不等于下面概述的位数.
伪代码
>计算表示你的号码所需的位数:n_needed_bits
>检查您的PRNG返回的位的大小:n_bits_prng
>计算需要的样本数:needed_prng_samples = ceil(n_needed_bits / n_bits_prng)
>真的:
> require_prng_samples(调用PRNG)次&连接所有获得的位
>检查结果的数字是否在您的范围内
>是?:返回号码(已完成)
>否?:do nothing(循环继续;将重新取样所有组件!)
备注
>这是一个acceptance-sampling / rejection-sampling的形式
>方法是一个Las-vegas type of algorithm:运行时在理论上没有约束
>所需的循环次数是平均值:n_possible-sample-number-of-full-concatenation / n_possible-sample-numbers-within-range
>根据拒绝方法的完全重采样(如果结果不在范围内)可以获得更多的非偏差/均匀性的正式分析,这对于这种方法是非常重要的一个方面
>当然,PRNG输出的经典假设是需要这样做的.