我想用随机输入运行测试,并且需要生成“合理的”随机数,即匹配得足以通过测试函数的先决条件的数字,但希望在其代码内部造成更严重的破坏。
math.random()
(我正在使用 Lua)产生均匀分布的随机数。将这些按比例放大将产生比小数字更多的大数字,并且整数将非常少。
我想以一种强烈支持“简单”数字的方式倾斜随机数(或使用旧函数作为随机源生成新的),但仍将覆盖整个范围,即扩展到正/负无穷大(或±1e309
为double
)。这表示:
- 最多十个数字应该是最常见的,
- 整数应该比分数更常见,
- 以 0.5 结尾的数字应该是最常见的分数,
- 其次是 0.25 和 0.75;然后是 0.125,
- 等等。
不同的描述:固定一个基本概率x使得概率总和为 1,并将数字n的概率定义为x k
其中k是其中n被构造为超现实数1的世代。这将x分配给 0,x 2分配给 -1 和 +1,
x 3分配给 -2,-1/2,+1/2 和 +2,依此类推。这很好地描述了接近我想要的东西(它有点倾斜),但几乎无法用于计算随机数。结果分布在任何地方都不是连续的(它是分形的!),我不确定如何确定基本概率x
(我认为对于无限精度,它将为零),并且基于此通过迭代计算数字非常慢(花费近乎无限的时间来构造大数字)。
有谁知道一个简单的近似值,给定一个均匀分布的随机源,会产生如上所述非常粗略分布的随机数?
我想进行数千次随机测试,数量/速度比质量更重要。尽管如此,更好的数字意味着更少的输入被拒绝。
Lua 有 JIT,所以性能通常不是什么大问题。然而,基于随机性的跳跃会破坏每一个预测,而且许多调用math.random()
也会很慢。这意味着封闭公式将比迭代或递归公式更好。
1维基百科有一篇关于超现实数字的文章,图片很好。一个超现实数是一对两个超现实数,即x := {n|m}
,它的值是这对中间的数,即(对于有限数){n|m} = (n+m)/2
(作为有理数)。如果该对的一侧为空,则将其解释为递增(或递减,如果右侧为空)。如果两边都是空的,那就是零。最初,没有数字,所以唯一可以建立的数字是0 := { | }
. 在第二代中,我们可以构建数字{0| } =: 1
,而在第三代中,{ |0} =: -1
我们得到
{1| } =: 2
、和(加上一些更复杂的已知数字表示,例如)。请注意,例如{|1} =: -2
{0|1} =: 1/2
{-1|0} =: -1/2
{-1|1} ? 0
1/3
永远不会由有限数生成,因为它是一个无限小数——浮点数1/3
也是如此,永远不会精确表示。