随机数重排求和差出现重复值的原因探究
为什么MATLAB和Python中会出现重复的浮点求和差值?
测试代码
MATLAB代码
g0 = randn(1, 100); g1 = g0; g1(2:end) = flip(g1(2:end)); sprintf("%.15e", sum(g0) - sum(g1))
Python代码
import numpy as np g0 = np.random.randn(100) g1 = g0.copy() g1[1:] = g1[1:][::-1] print(sum(g0) - sum(g1))
观察到的现象
多次执行后,求和差值会重复出现如下特定小数值(或其相反数):
8.881784197001252e-15 3.552713678800501e-15 2.6645352591003757e-15 4.440892098500626e-16 1.7763568394002505e-15
原因解析
这本质是浮点数的二进制存储精度限制导致的,具体拆解为三点:
翻转操作未改变元素,但改变了求和顺序
从数学逻辑上看,g1只是把g0从第2个元素开始翻转,元素本身完全一致,理论上两次求和结果应该相等。但实际中,浮点数是二进制的近似表示,累加时的舍入误差会随求和顺序变化而产生细微差异——不同的累加顺序会让舍入误差的累积方式改变,最终出现可观测的差值。差值都是双精度浮点数最小精度的整数倍
你看到的所有差值,都是2^-53(约1.1102230246251565e-16)的整数倍:比如8.881784197001252e-15是80 * 2^-53,3.552713678800501e-15是32 * 2^-53。这是因为MATLAB和numpy默认都使用IEEE 754标准的双精度浮点数,其最小可分辨精度就是2^-53,所有舍入误差必然是这个值的整数倍,所以差值只会出现这些固定的组合。跨语言一致的核心原因
在Windows 11平台下,MATLAB R2023a和Python 3.11+numpy 1.24.4都遵循IEEE 754双精度浮点数标准,randn生成的随机数最终都会转成标准双精度格式,求和运算的底层实现也遵循相同的浮点运算规则,因此会出现完全一致的误差值。
内容的提问来源于stack exchange,提问作者OverLordGoldDragon
相关产品推荐
相关产品推荐

