我想用随机输入运行测试,需要生成'明智'随机 数字,即匹配足以传递测试函数的数字 先决条件,但希望在其代码中深入破坏。
math.random()
(我正在使用Lua)产生均匀分布的随机数
数字。扩大这些数字将提供比小数字更大的数字,
并且整数很少。
我想扭曲随机数(或使用旧数生成新数据)
作为一个随机性来源,以一种强烈支持“简单”数字的方式,
但仍将覆盖整个范围,即延伸至正/负无穷大
(或±1e309
代表double
)。这意味着:
不同的描述:修复基本概率 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()
也会很慢。这意味着封闭的公式将优于a
迭代或递归的。
1 维基百科有一个article on surreal numbers
一个nice picture。一个超现实的数字是一对两个超现实主义
数字,即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
从未完全表示。
答案 0 :(得分:1)
算法怎么样?
floor((float_val << roundoff)+0.5)
)答案 1 :(得分:1)
对于类似超现实的十进制扩展,您需要一个随机二进制数。 偶数位告诉您是停止还是继续,奇数位告诉您是在树上向右还是向左:
> 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()中的十进制数字,并将0-4替换为'1',将5-9替换为'1':
0.8430419054348022
变
1000001010001011
变为-0.5
0.5513009827118367
变
1100001101001011
变为0.25
等
没有做过多的lua编程,但在Javascript中你可以这样做:
Math.random().toString().substring(2).split("").map(
function(digit) { return digit >= "5" ? 1 : 0 }
);
或真正的二进制扩展:
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之间返回,很少有大数字出现。
请注意,此分布的平均值和总和趋向于偏向大的负数或正数,因为运行它的次数越多,分母中的小数字就越有可能导致数字“爆炸“大量涌现,例如147,967或-194,137。
请参阅gist了解示例代码。
答案 2 :(得分:0)
您可以立即计算第n个出生的超现实数字。
例如,第1000个超现实数字是:
转换为二进制:
1000年12月= 1111101000 bin
1变成加号,0变成负号>
1111101000
+++++-+ ---
第一个'1'位是0值,下一组相似的数字是+1(代表1)或-1(代表0),然后值是1 / 2、1 / 4、1 / 8,以此类推。
1 1 1 1 1 0 0 0 0 0
++ + + +-+---
0 1 1 1 1 h h h h h h
+ 0 + 1 + 1 + 1 + 1-1 / 2 + 1 / 4-1 / 8-1 / 16-1 / 32
= 3 + 17/32
= 113/32
= 3.53125
此表示形式的二进制长度(以位为单位)等于该数字的出生日期。
一个超现实数字的左,右数字是二进制表示形式,其尾部分别剥去了最后的0或1。
超现实数字在-1和1之间均匀分布,其中存在到特定日期创建的数字的一半将存在。 1/4的数字均匀分布在-2至-1和1至2之间,依此类推。最大范围是从负数到正整数,与您提供的天数相匹配。这些数字缓慢地变为无穷大,因为每天只向负数和正数范围加一个,并且天数是最后一个数的两倍。
编辑:
此位表示形式的好称呼是“ sinary”
负数是换位。例如:
100010101001101s -> negative number (always start 10...)
111101010110010s -> positive number (always start 01...)
我们注意到所有位翻转都接受第一个换位。
Nan => 0s(因为所有其他数字均以1开头),这非常适合在计算机的位寄存器中表示,因为需要前导零(我们不再将三进制计算机变成……太糟糕了)
所有Conway超现实代数都可以在这些数字上完成,而无需转换为二进制或十进制。
正弦格式可以看做是一个加一个简单的计数器并附加一个2的补码十进制表示形式。
以下是关于结业的不完整报告(类似于罪恶):https://github.com/peawormsworth/tools/blob/master/finary/Fine%20binary.ipynb