刚才有人问为什么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
我相信对于浮点数,加法是可交换的(即a + b == b + a
)。我们有三种选择,第一对可以相加然后有一种选择;对于第二次加法,所以三个和是我们仅用三个值所能得到的最大值。
?正如Eric刚才指出的,对于三个以上的值,也有不同的可能性,而不仅仅是从左到右求和,例如(a+b) + (c+d)
。我对加数字的方法很感兴趣。
注意我说的是64位浮点数(我是Python爱好者,我知道在其他语言中它们通常被称为双精度浮点数)。
你当然可以。对于您的具体问题:
我们能得到三个以上不同的和和的四个值吗?
下面的一组值可以说明情况确实如此:
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)
当我运行这个,我得到:
1.36873053731e+48
1.370157785e+48
1.46007438964e+48
1.46150163733e+48
它们都是不同的
对于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)
这个打印:
-8.90029543403e-308
1.73833895196e-310
-4.45041933248e-308
-8.88291204451e-308
0.0
再次,结果各不相同。
如果你能找到任何足够大的n(也许n>2就足够了)的n
值,这样所有不同的排列都会产生不同的和,我不会感到惊讶;对那些由于交换性而等价的取模。(当然这只是猜测。)使用灾难性取消,您可以安排结果有很大的不同。
如果你有N个浮点数,你就有N个!可能的序列如何添加它们。假设每次只做一个加法,结果是0.5[N*(N-1)]*(N-2)!计算的版本。(假设第一对的a+b=b+a,并且a+b与b+a的四舍五入相同)。每一步之后都有一个舍入误差。只要你不强制计算序列,我期望是N!/2由于舍入误差导致的可能结果。但是,只要使用纯正数,差异应该在最低有效数字上。
如果你做的事情像减去非常相似的数字(例如:9999999.9+(-9999999.8)),舍入误差可能变得很严重(取决于你的浮点数的大小)。
使用括号可以得到更多的组合(例如:(a+b)+(c+d)可能与((a+b)+c)+d不同,因为您强制对每一对括号进行四舍五入。