Random 为测试生成强偏倚随机数

Random 为测试生成强偏倚随机数,random,lua,automated-tests,distribution,Random,Lua,Automated Tests,Distribution,我想用随机输入运行测试,并需要生成“合理的”随机输入 数字,也就是说,匹配好的数字足以通过测试函数的 先决条件,但希望在其代码内部造成更大的破坏 math.random()(我使用Lua)生成均匀分布的随机变量 数字。扩大规模将产生比小数字多得多的大数字, 而且会有非常少的整数 我想扭曲随机数(或使用旧的随机数生成新的随机数) 作为随机性源)以强烈支持“简单”数字的方式, 但仍将覆盖整个范围,即扩展到正/负无穷大 (或±1e309用于双精度)。这意味着: 比如说,最多10个数字应该是最常见的

我想用随机输入运行测试,并需要生成“合理的”随机输入 数字,也就是说,匹配好的数字足以通过测试函数的 先决条件,但希望在其代码内部造成更大的破坏

math.random()
(我使用Lua)生成均匀分布的随机变量 数字。扩大规模将产生比小数字多得多的大数字, 而且会有非常少的整数

我想扭曲随机数(或使用旧的随机数生成新的随机数) 作为随机性源)以强烈支持“简单”数字的方式, 但仍将覆盖整个范围,即扩展到正/负无穷大 (或
±1e309
用于
双精度
)。这意味着:

  • 比如说,最多10个数字应该是最常见的
  • 整数应该比分数更常见
  • 以0.5结尾的数字应该是最常见的分数
  • 其次是0.25和0.75;那么0.125,
  • 等等
另一种描述:固定一个基本概率x,这样概率 将求和为1,并将数字n的概率定义为xk 其中k是n被构造为超现实的一代 编号1。将x赋值为0,x2赋值为-1和+1, x3到-2、-1/2、+1/2和+2,依此类推。这 给出了一个很好的描述接近我想要的东西(它也有点歪斜) 但对于计算随机数几乎是不可用的。结果 分布是不连续的(它是分形的!),我不知道该怎么做 确定基本概率
x
(我认为对于无限精度,它将是 零),并且基于此通过迭代计算数字是非常困难的 缓慢(花费几乎无限的时间来构造大量的数字)

有没有人知道一个简单的近似,给定一个均匀分布的 随机性源,产生随机数,随机数大致分布为 如上所述

我想运行数千个随机测试,数量/速度更高 比质量更重要。尽管如此,更好的数字意味着更少的输入被拒绝

Lua有一个JIT,所以性能通常不是什么大问题。然而,跳跃是基于 on randomness将破坏每个预测,并多次调用
math.random()
也会很慢。这意味着一个封闭的公式将优于一个封闭的公式 迭代的或递归的


1维基百科有一个 A.超现实数字是两个超现实数字的一对 数字,即<代码> x:{{n} M},其值是中间的数字。 配对,即(对于有限数)
{n | m}=(n+m)/2
(作为有理数)。如果一方 该对的值为空,这被解释为递增(或递减,如果正确的话) 是空的)一个。如果两边都是空的,那就是零。最初,有 没有数字,因此唯一可以构建的数字是
0:={124;}
。世代 两个一可以构建数字
{0}=:1
{0}=:-1
,我们得到三个
{1}=:2
{1}=:-2
{0}1}=:1/2
{-1}0}=:-1/2
(加上一些 已知数字的更复杂表示,例如
{-1 | 1}?0
)。注意 e、 g.
1/3
从来不是由有限数生成的,因为它是无限的
分数–浮点数也是如此,
1/3
永远不会精确表示。

这对于算法来说是什么

  • 使用库函数生成(0,1)中的随机浮点
  • 根据期望的概率密度函数生成随机整数舍入点(例如,概率为0.5的0,概率为0.25的1,概率为0.125的2,…)

  • 通过该舍入点对浮点进行“舍入”(例如,
    floor((float_val)对于超现实的十进制扩展,您需要一个随机二进制数。
    偶数位告诉您是停止还是继续,奇数位告诉您在树上是向右走还是向左走:

    > 0... => 0.0 [50%] Stop
    > 100... => -0.5 [<12.5%] Go, Left, Stop
    > 110... => 0.5 [<12.5%] Go, Right, Stop
    > 11100... => 0.25 [<3.125%] Go, Right, Go, Left, Stop
    > 11110... => 0.75 [<3.125%] Go, Right, Go, Right, Stop
    > 1110100... => 0.125
    > 1110110... => 0.375
    > 1111100... => 0.625
    > 1111110... => 0.875
    
    或真正的二进制扩展:

    Math.random().toString(2).substring(2)
    
    不确定哪个是真正的“随机”——你需要测试它

    你可以用这种方法生成超现实的数字,但大多数结果都是a/2^b形式的小数,整数相对较少。在第3天,只生成2个整数(-3和3)对6个小数,在第4天是2对14,在第n天是2对(2^n-2)

    如果将
    math.random()
    中的两个均匀随机数相加,将得到一个新的分布,该分布具有类似“三角形”的分布(从中心线性递减)。添加3或更多将得到一个以0为中心的更类似“钟形曲线”的分布:

    math.random() + math.random() + math.random()  - 1.5
    
    除以一个随机数将得到一个真正的野生数:

    A/(math.random()+1e-300)
    
    这将返回介于A和(理论上)A*1e+300之间的结果, 虽然我的测试显示50%的时间结果在A和2*A之间 大约75%的时间在A和4*A之间

    把它们放在一起,我们得到:

    round(6*(math.random()+math.random()+math.random() - 1.5)/(math.random()+1e-300))
    
    这使得70%以上的数据返回到-9到9之间,很少出现一些大的数据

    请注意,此分布的平均值和总和将趋向于向一个较大的负数或正数发散,因为运行它的次数越多,分母中的一个较小的数字越有可能导致该数字“爆炸”为一个较大的数字,如147967或-194137

    有关示例代码,请参见


    您可以立即计算第n个出生的超现实数字

    例如,第1000个超现实数字是:

  • 转换为二进制:

    1000年12月=1111101000箱

  • 1变成正0变成负:

    1111101000

    +++++-+---

  • 第一个“1”位为0值,下一组类似数字为+1(对于1)或-1(对于0),然后每个后续位的值为1/2、1/4、1/8等

    11101000

    ++++++-+--

    011小时

    +0+1+1+1+1-1/2+1/4-1/8-1/16-1/32

    =3+17/32

    =113/32

    =3.53125

  • 此代表的二进制长度(以位为单位)
    round(6*(math.random()+math.random()+math.random() - 1.5)/(math.random()+1e-300))
    
    100010101001101s -> negative number (always start 10...)
    
    111101010110010s -> positive number (always start 01...)