我们可以从很少的浮点数中得到多少种不同的总和?

don*_*ode 9 math floating-point floating-accuracy ieee-754

有人刚刚问为什么sum(myfloats)不同sum(reversed(myfloats))。很快就被骗到浮点数学坏了吗?并删除。

但这让我很好奇:仅仅通过以不同的顺序求和,我们可以从很少的浮点数中得到多少个不同的总和?使用三个浮点数,我们可以得到三个不同的总和:

>>> from itertools import permutations
>>> for perm in permutations([0.2, 0.3, 0.4]):
        print(perm, sum(perm))

(0.2, 0.3, 0.4) 0.9
(0.2, 0.4, 0.3) 0.9000000000000001
(0.3, 0.2, 0.4) 0.9
(0.3, 0.4, 0.2) 0.8999999999999999
(0.4, 0.2, 0.3) 0.9000000000000001
(0.4, 0.3, 0.2) 0.8999999999999999
Run Code Online (Sandbox Code Playgroud)

我相信加法对于浮点数来说是可交换的(即a + b == b + a)。我们对第一对相加有三个选择,然后对第二个相加有一个“选择”,所以三个和是我们仅用三个值就能得到的最多结果。

我们可以得到三个以上具有四个值的不同总和吗?经过一些实验,我没有发现这样的情况。如果我们不能:为什么不呢?如果可以的话:有多少?有多少?

正如埃里克刚刚指出的,对于三个以上的值,除了从左到右求和之外,还有不同的可能性,例如(a+b) + (c+d)。我对任何添加数字的方式感兴趣。

注意我说的是 64 位浮点数(我是 Python 爱好者,我知道在其他语言中它们通常被称为双精度浮点数)。

ali*_*ias 1

你当然可以。对于您的具体问题:

我们可以得到三个以上具有四个值的不同总和吗?

这是一组值来表明情况确实如此:

v0 = -1.5426605224883486e63
v1 =  7.199082438280276e62
v2 =  8.227522786603223e62
v3 = -1.4272476927059597e45

print (v0 + v2 + v1 + v3)
print (v3 + v1 + v0 + v2)
print (v2 + v1 + v0 + v3)
print (v1 + v2 + v3 + v0)
Run Code Online (Sandbox Code Playgroud)

当我运行这个时,我得到:

1.36873053731e+48
1.370157785e+48
1.46007438964e+48
1.46150163733e+48
Run Code Online (Sandbox Code Playgroud)

所有这些都是不同的。

对于 5,这是一个示例集:

v0 = -8.016918059381093e-292
v1 =                    -0.0
v2 = 2.4463434328110855e-296
v3 =  8.016673425037811e-292
v4 =   1.73833895195875e-310

print(v4 + v1 + v0 + v2 + v3)
print(v2 + v3 + v0 + v1 + v4)
print(v4 + v3 + v1 + v0 + v2)
print(v1 + v0 + v2 + v3 + v4)
print(v1 + v4 + v2 + v0 + v3)
Run Code Online (Sandbox Code Playgroud)

这打印:

-8.90029543403e-308
1.73833895196e-310
-4.45041933248e-308
-8.88291204451e-308
0.0
Run Code Online (Sandbox Code Playgroud)

再次,结果不同。

n如果您可以找到任何足够大的 n(也许 n>2 就足够了)的值,这样所有不同的排列都会产生不同的总和,我不会感到惊讶;对由于交换性而等价的那些进行模。(当然,这只是一个猜想。)如果发生灾难性的取消,您可以安排结果有很大不同。