perl – 如何在0和bigint之间选择一个随机值?

我有一个组合问题,我想要在0和大整数之间随机选择一个整数.

我目前的做法不足

现在,对于常规的整数我通常会写一些类似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输出的经典假设是需要这样做的.

>如果PRNG例如在低位/高位(如上所述)方面具有一些不均匀性,则这将具有上述输出的效果

相关文章

1. 如何去重 #!/usr/bin/perl use strict; my %hash; while(...
最近写了一个perl脚本,实现的功能是将表格中其中两列的数据...
表的数据字典格式如下:如果手动写MySQL建表语句,确认麻烦,...
巡检类工作经常会出具日报,最近在原有日报的基础上又新增了...
在实际生产环境中,常常需要从后台日志中截取报文,报文的形...
最近写的一个perl程序,通过关键词匹配统计其出现的频率,让...