提问人:OverLordGoldDragon 提问时间:8/14/2023 最后编辑:OverLordGoldDragon 更新时间:8/14/2023 访问量:87
随机数重新排序的总和合并为重复值
Sums of random number reorderings combine to recurring values
问:
g0 = randn(1, 100);
g1 = g0;
g1(2:end) = flip(g1(2:end));
sprintf("%.15e", sum(g0) - sum(g1))
g0 = np.random.randn(100)
g1 = g0.copy()
g1[1:] = g1[1:][::-1]
print(sum(g0) - sum(g1))
在 Python 和 MATLAB 中,重新运行这些命令足够多次将重复以下值(或其否定值;不完整列表):
8.881784197001252e-15
3.552713678800501e-15
2.6645352591003757e-15
4.440892098500626e-16
1.7763568394002505e-15
事实上,我第一次和第二次运行它们 - 它们完全相同,让我认为它们在系统级别上共享 RNG 有延迟......(但忽略这个问题)。mat -> py -> mat -> py
我很快就会摔倒在地板上,而不是这个巧合,再加上不同的语言。
发生了什么事情?
Windows、Python、numpy、MATLAB、11
3.11.4
1.24.4
9.14.0.2286388 (R2023a) Update 3
答:
2赞
Cris Luengo
8/14/2023
#1
您的价值观列表:
8.881784197001252e-15
3.552713678800501e-15
2.6645352591003757e-15
4.440892098500626e-16
1.7763568394002505e-15
比赛
>> [40,16,12,2,8].' * eps
ans =
1.0e-14 *
0.888178419700125
0.355271367880050
0.266453525910038
0.044408920985006
0.177635683940025
完全可以预料到,您会遇到此范围内的舍入误差。在两个不同的系统中获得完全相同的两个值并不是那么大的巧合。这是偶然发生的。
eps
是机器 epsilon,您可以将其与 1 相加以获得下一个数字的最小值。添加 100(单位正态)随机值的结果大多恰好在 1-32 范围内,较小的值更有可能。我们还希望舍入误差小于结果的精度。因此,我们应该能够将这些数字写成:<small integer> * eps(<binary magnitude of result>)
8.881784197001252e-15 == 5 * eps(8)
3.552713678800501e-15 == 1 * eps(16)
2.6645352591003757e-15 == 3 * eps(4)
4.440892098500626e-16 == 1 * eps(2)
1.7763568394002505e-15 == 1 * eps(8)
另请注意,MATLAB 最近更改了其 sum
的实现,明确地减少了舍入误差。并且 NumPy 使用类似的策略对数组中的值求和。
评论
1赞
Cris Luengo
8/14/2023
1e100
是一个有效的浮点数,也是。但是,如果将它们加在一起,第二个远低于第一个可以表示的大小,因此结果将等于第一个。想象一下,您有 3 位十进制精度(带有任意指数)。你可以精确地表示 10.0,也可以表示 0.001。将它们相加得到 10.001,但您只有 3 位精度,因此必须将其四舍五入为 10.0。 是 ,您可以将其加到 1 以获得下一个可表示的浮点数的最小值。[续]1e-100
eps
eps(1)
0赞
Cris Luengo
8/14/2023
[续]将 100 个值相加预计会产生一个相对较小的值,可能是 4 个,也许是 16 个。当然,有时它会更大或更小。无论如何,从 4 向上的下一个值是 ,从 16 向上的下一个值是 。这就是您在此处执行的操作的精度。[请注意,我在这里故意使用 2 的幂,5 和 4 在二进制中具有相同的大小。randn
eps(4) == 4*eps
eps(16) == 16*eps
eps(5) == eps(4)
0赞
OverLordGoldDragon
8/15/2023
eps(x)
返回 足够不同的唯一值,但不返回任何不同的 的唯一值。 7 到 11,1E6 试验的平均 8.65。我想这是在理性的范围内,尽管我仍然觉得我不太可能经常重复。我想这是更有可能的,因为不同的舍入实现可以取消。还有(2)。-- (1)你说“是有效的浮点”,那么“不能表示为浮点”?-- (2) 有总和内四舍五入,因此我的前 (1) - 另请参阅 sum 与 np.sumx
x
numel(unique(eps(randn(1, 100)))) ==
1e-100
1赞
Cris Luengo
8/15/2023
@OverLordGoldDragon“是一个无法精确表示的有效浮点数” 您可以表示它,但会有一个小的舍入误差。 无效,则根本无法表示,并且四舍五入为 0。 取决于 的(二进制)数量级,而不是它的确切值。它是数字中最低位的值。当您将指数增加 1 时,最低位的值将加倍。所以 1 和 2 之间的所有数字都是一样的,2 和 4 之间的所有数字都是双倍的,4 和 8 之间的所有数字都是双倍的,依此类推。1e-600
eps(x)
x
eps
1赞
Cris Luengo
8/15/2023
@OverLordGoldDragon 这里有一些关于浮点的更多读物。这是一个非常复杂的话题,有很多细节和陷阱。这是参考,以防你喜欢硬数学。这是那篇论文的简化版(虽然我没有读过,但我不知道它是否足够详细来帮助你)。
评论
0
sum(g0)
sum(g1)
2.220446049250313e-16 1.0386152428024817 1.0386152428024815
1.0386152428024817 - 1.0386152428024815