Python中两个浮点数的加法和减法

计算科学 Python 浮点 精确
2021-12-21 21:30:59


昨天我想知道浮点数是如何在计算机中处理的,以及它们在二进制中的样子……我了解了单精度浮点数,并试图了解这种格式的限制……

我首先编写了这个小 Python (3.4) 脚本

a,b = 1,1

while (a+b)-a-b == 0:
    a*=2.0

while (a+b)-a-b != 0:
    b+=1.0

print(a,b)

我想看看 a 的特定指数值可能会导致结果(a+b)-ab缺乏精度,以及增加b的值是否可以纠正它。

输出是:

9007199254740992.0 2.0

我注意到2^53 = 9007199254740992.0虽然这有点令人不安:53的二进制表示是110101,这看起来真的不像任何特定值......

2.0 ”让我不那么怀疑了,因为您只需添加1即可增加b的指数值。它更有意义,但我意识到我也无法正确解释它。

我修改了我的脚本以查看我所做的一切的实际二进制值:

import struct

def binary(f):
    return str(bin(struct.unpack('!i',struct.pack('!f',f))[0])).replace('0b', '')

def status(a,b):
    return binary(a),binary(b),binary(a+b),binary(-a),binary(-b),binary(-a-b),binary((a+b)-a-b)

a,b = 1,1

while (a+b)-a-b == 0:
    a*=2.0
    print(status(a,b))


print("\n")

while (a+b)-a-b != 0:
    b+=1.0
    print(status(a,b))

print(a,b)

但我所看到的对我没有帮助。我无法弄清楚为什么在 a 的特定值处会出现精度不足的情况以及为什么只增加一次b就可以纠正它。

谁能帮我理解这一点?

(我提前为我的英语很差道歉)

1个回答

您遇到了双精度浮点数固有的限制,python 将其用作其默认浮点类型(这与 C 双精度相同)。

这些模型实数为

(1)s(1+i=152b52i2i)×2e1023

在哪里s为 0 或 1(1 位),e是一个 11 位数字,并且bis 填充剩余的位。这确实具有整数步幅的最大值 253= 9007199254740992.0。在这个值之后,可以建模的数字开始每次增加2,并且增加1.0(即b)会下溢。另一方面,您仍然可以添加 2.0 就好了。

该模型有效地尝试平衡范围(它接受的指数大小)和准确性(它接受的量化步长的大小)。如果您仍然想使用单精度数字并且您的 python 安装包含 numpy,则可以使用numpy.float32函数访问它们。请注意,您还必须将常量设置为 float32,否则 python 自动类型转换可能会阻止您看到任何内容。