跳到主要内容
CalcMax

随机数生成器

范围:1 – 200

范围:0 – 4,294,967,295

结果

63, 1, 53, 99, 97

生成的随机数

可能的取值个数
100
至少出现一对重复数字的概率
9.65%

随机数生成器从一个起点出发,生成你指定区间内的一串整数。这一页收三个东西——区间、要几个数、以及作为起点的随机种子——然后原样吐出那么多个整数,而且同一个种子永远给出同一串数。这正是它相对于随手一个随机函数的用处:把一个一次性的结果变成可以交给别人复现、可以当面重跑、可以拿来当测试用例的东西。关掉重复,结果就从「序列」变成「抽取」,同一个值不会出现两次;开着重复,每个位置各自独立地取一个值,这才是骰子、摇号机、可能重复的播放列表的诚实模型。面板还会给出这个区间一共有多少个不同的值,以及允许重复时撞上同一个数的概率。

公式

next = (state + 0x6D2B79F5) 经乘法移位混合 → value = minimum + ⌊next × (maximum − minimum + 1)⌋

seed
生成器的起始状态,可以取 0 到 4294967295 之间的任意整数。它本身不是随机源,只是这串数开始的地方——这正是同一个种子永远给出同一串数的原因
state
运行中的状态,每生成一个数就更新一次。更新用一个固定常数和几步乘法移位把状态搅乱;让它看起来无关的就是这几步,要把它简化掉,第一个坏掉的就是它
minimum, maximum
区间的两个端点,都包含在内。区间的宽度就是这个小数被缩放的倍数,所以区间里每个整数被取到的机会一样
⌊ ⌋
向下取整。生成器给出的是 [0, 1) 上的小数,取整把它落到区间里的某一个整数上
count
要生成几个数,最多 200 个。关掉重复时它不能超过区间里的取值个数——抽出来的子集不可能比池子还大

需要一串数而不是一个数的时候用它:手工核对用的抽样、每次跑都必须一样的测试数据、需要当众重跑一次的抽签、或者占位数据。种子能固定下来,正是它比随手一个随机函数更合适的地方——种子把一个一次性的结果变成可以共享、可以复查、可以拿出来讲道理的东西。同一个值不允许出现两次时(抽签、从名单里抽样、洗牌)就把重复关掉。两件事不要用它做:它不是不可预测的来源,凡是需要「谁都猜不到」的场合都不该找它;它也不等于对真实总体的随机抽样——它只知道区间,对总体一无所知。

算例

  1. 1 到 100 里取 5 个数,再来一次还是这 5 个

    1. 1 到 100 一共有 100 个不同的值,所以每次取数都是 100 里挑一个
    2. 种子 1 确定了起始状态,五个数各自把它更新一次
    3. 把每次得到的小数向下取整落到 1 到 100 里,依次得到 63、1、53、99、97

    这五个数不是巧合,也不是事先存好的表:它就是种子 1 的结果,在种子那一栏重新填 1 会一模一样地再给一次。注意 9.65% 说的是区间与个数,不是这一次抽取——从 100 个值里抽 5 个,撞上一对的概率略低于十分之一,至于这一串里有没有撞上,那是另一回事。把种子改成 7 会换一整串数,而这个百分比纹丝不动,这是看清「面板上哪一半是随机的、哪一半是算出来的」最干净的办法。

  2. 1 到 49 里取 6 个数,不许重复

    1. 池子是 49 个值,要从里面不放回地取 6 个
    2. 每取一个新数,如果池子已经给过它就重取,所以一个值不可能出现两次
    3. 按抽取顺序读出来就是 23、16、33、31、8、11

    把重复关掉并不会改变 27.26%,而这正是把它印在这条算例旁边的意义:它是「6 次抽取如果允许重复,撞上的机会有多大」,与你有没有禁止重复无关。它也说明了为什么大数目下的不重复抽取会越来越贵——49 个池子取 6 个,已经超过四分之一的无限制抽法会撞号;而 365 个池子取到 23 个,这个数就过半了。列表按抽取顺序给出而不排序,就是为了同一个种子加同一组设置永远复现同一串数。

  3. 区间里只有一个值

    1. 区间里只有一个值,所以每次取到的都是它
    2. 撞号概率问的是 4 次抽取撞上的机会,池子只有一个值时必须撞上
    3. 结果是 7、7、7、7

    这是随机数生成器不再随机、退化成常数的边界,值得记住,因为这是唯一一种「还没按就已经能全说准」的情况。它同时也是不重复模式的边界:同一个区间下要取 2 个不重复的数,那不是一个短一点的列表,而是一个做不到的请求,这一页会直接说出来,而不是悄悄少给一个数。

局限

这些数不能用在任何需要「谁都猜不到」的地方。它用的是普通软件里那种又快又小的种子式算术序列:知道种子就能复现整串数,知道其中几个值就能推出其余的。所以密码、密钥、令牌、一次性验证码、带钱的抽奖,以及任何参与者不该能预测或还原结果的场合,都不该用它——那些场合只有密码学随机源才是对的答案。撞号概率也不是对「你眼前这一串」的判断:它是在「各次抽取独立且均匀」的前提下,算这一组抽取里至少出现一对相同值的概率,而且无论你有没有禁止重复都会给出来。它的实际含义恰好是容易反直觉的那一面——池子大小的平方根量级就足以让撞号变得很可能,所以 365 天里取 23 个生日就已经过半。单次最多 200 个数,且个数超过池子大小时不重复模式无解。

常见问题

这些数能用在抽奖、密码或者安全令牌上吗?
不能。它是普通软件里那种种子式算术序列,不是密码学随机源:知道种子就能复现整串数,知道其中几个值就能推出其余的。凡是参与者不该能预测或还原结果的场合——带钱的抽奖、密码、密钥、令牌、一次性验证码——都要换成密码学随机源。而抽签、抽样、游戏、测试数据这些「可复现是优点而不是漏洞」的场合,它才正好合适。
种子是干什么的?为什么每次给我的数都一样?
种子就是这串数开始的状态,所以同一个种子永远给出同一串数,这是有意的:它让结果可复现,而这正是你要把一份抽样交给别人、当众重跑一次抽签、或者不让测试用例漂移时需要的。换一个种子,同一组设置就换一串数。想让每次都不一样,就在两次之间改种子——你填进去的值会跟着结果一起给出,所以喜欢的那一串随时能找回来。
允许重复的时候,为什么还会真的撞上?
因为每次抽取互相独立。允许重复时,每个位置各自从区间里挑一个值,不管别的位置挑了什么,而这正是骰子、或者把球放回去的摇号机的诚实模型。面板上的撞号概率就是「至少有一对相同」的概率——100 个值里取 5 个约 9.65%,从 365 个值里取 23 个就过半了。同一个值不允许出现两次时(抽签、从名单里抽样、洗牌)就把重复关掉。
禁止重复以后,撞号概率会变小吗?
不会,而且面板是故意照旧显示的。它回答的正是你拨动那个开关时真正关心的问题:如果不禁止重复,本来有多大机会撞上。1 到 49 里取 6 个数是 27.26%,所以禁止重复挡掉的是一份真实存在的风险,不是什么理论上的可能性。它也解释了大数目下的不重复抽取为什么会变慢乃至无解——个数一旦超过区间里的取值个数就根本没有合法答案,这一页会直接说明,而不是返回一个短一点的列表。
一次能生成多少个数?区间有什么限制?
一次最多 200 个数;区间端点必须是整数,且最小值不能大于最大值。取值本身可以是负数,所以 −50 到 50 这样的区间是可以的。端点是非整数时会直接报错而不是四舍五入:在不重复模式下,从一个含小数的区间里抽取会让「不重复」这条规则失去意义,而一个看起来合理、实际却违反了自身设置的列表,比一条错误信息糟得多。
生成的数会排序吗?
不会——它按抽取顺序打印,而这个顺序是结果的一部分。排序会丢掉「同一个种子要复现」的那份信息,并且在位置本身有意义的地方(比如排一个乱序、发一手牌)会直接改变含义。想要有序的抽取结果,复制出去自己排一遍;抽取本身保持种子给出的那个顺序。

参考资料

相关计算器