我们可以从很少的浮动中获得多少不同的金额?

How many different sums can we get from very few floats?

提问人:no comment 提问时间:9/15/2021 最后编辑:Olivierno comment 更新时间:10/14/2021 访问量:362

问:

有人只是问为什么与.很快被骗到浮点数学坏了吗?并删除了。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

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

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

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

数学 IEEE-754 浮点精度

评论

0赞 Machavity 9/19/2021
评论不用于扩展讨论;此对话已移至 Chat

答:

1赞 alias 9/17/2021 #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)

当我运行它时,我得到:

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

评论

0赞 kcsquared 9/18/2021
您是否使用任何特定方法来生成这些示例并导致灾难性的取消?如果你知道任何合理的原则性方法来抽样这样的列表,那将非常有助于测试你关于列表存在的猜想,这样“所有不同的排列都会产生足够大的 n 的不同和模交换性”,我认为这对 n>3 是错误的。
1赞 alias 9/18/2021
我使用了 SMT 求解器(特别是 z3),它可以处理浮点逻辑。(smtlib.cs.uiowa.edu/theories-FloatingPoint.shtml)关于猜想:你很可能是对的,虽然 SMT 求解器可用于为任何给定的混凝土找到此类示例,但很难使用它们来回答任意(符号)的查询。(此外,SMT 求解器会明显减慢速度,周围有更多符号值。需要进行适当的数值分析,这超出了我目前的技能范围。nn
0赞 kcsquared 9/18/2021
我从未使用过 SMT 求解器,所以我必须检查一下。由于 Python 的 float64 据说允许次正态数,我怀疑 Sterbenz 的引理对有多少排列可以给出唯一和的限制比交换性要强得多。交换性应该只会将排列减半,但是,正如帖子评论中所述,目前尚不清楚是否存在具有超过 9 个(12 个可能)不同和的 4 变量示例,而有许多示例恰好为 9。
1赞 alias 9/19/2021
@kcsquared SMT 求解器通常是用高级语言编程的,我使用 Haskell 中的 SBV 库来编写这个版本,它允许从 Haskell 编写 z3 脚本。不确定这对您有多大用处,但这是整个程序: gist.github.com/LeventErkok/75d0c0bad4a4415ca26d0a5a7eda95af 类似的程序也可以用 C/C++/Java/Python 等编写,尽管我发现 Haskell 非常简洁且易于使用。如果你想追求这个想法,我很乐意在这方面进一步合作。
1赞 no comment 9/19/2021
@kcsquared “什么是浮子的小扰动?”是指如何找到一些?我现在正在使用 math.nextafter
-1赞 Ricardo Erckert 10/14/2021 #2

If you have N floats you have N! possible sequences how to add them. Assuming you always do one addition at a time this leads to 0.5[N*(N-1)]*(N-2)! versions of the calculation. (assuming a+b=b+a for the first pair and a+b has the same rounding as b+a). After each step there is a rounding error. As long as you dont force the calculation sequence I would expect N!/2 possible results due to rounding errors. The differences however should be in the lowest significant digits as long as you work with pure positive numbers.

If you do things like substracting very similar numbers (example:9999999.9+(-9999999.8) the rounding errors can become critcal however (depending on the size of your floats).

Using brackets you can get even more combinations (Example: (a+b)+(c+d) may differ from ((a+b)+c)+d because you force a rounding with each pair of brackets.