为什么通过除法而不是乘法来精确表示二进制?
Why exact binary representation through division but not multiplication?
此问题的部分内容已在别处解决(例如 is floating point math broken?)。
以下揭示了除法与乘法生成数字的方式不同:
>>> listd = [i/10 for i in range(6)]
>>> listm = [i*0.1 for i in range(6)]
>>> print(listd)
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]
>>> print(listm)
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5]
第二种情况,0.3的舍入误差约为1e-16,双精度浮点数。
但是我不明白关于输出的三件事:
- 既然这里唯一可以用二进制精确表示的数字是 0.0 和 0.5,为什么上面打印的不是唯一精确的数字?
- 为什么这两个列表理解的评估不同?
- 为什么数字的两个字符串表示不同,但二进制表示不同?
>>> def bf(x):
return bin(struct.unpack('@i',struct.pack('!f',float(x)))[0])
>>> x1 = 3/10
>>> x2 = 3*0.1
>>> print(repr(x1).ljust(20), "=", bf(x1))
>>> print(repr(x2).ljust(20), "=", bf(x2))
0.3 = -0b1100101011001100110011011000010
0.30000000000000004 = -0b1100101011001100110011011000010
这里的关键点是 10
是用二进制表示的,而 0.1
不是。除以 10 可以得到每个分数最接近的表示;乘以 0.1 的不精确转换并不能保证精度。有时您会“足够接近”以将结果四舍五入到一位小数,有时则不然。
这些理由够吗?
回答每个问题:
- Since the only numbers here exactly representable in binary are 0.0 and 0.5, why aren't those the only exact numbers printed above?
Python 将任何浮点数的显示四舍五入为计算时产生相同值的最短文字。所以是的,其中许多数字实际上与它们代表的实际数字并不相同,但如果你在 Python 中输入它们,你会在没有数学的情况下得到那个(稍微不准确的)值。
- Why do the two list comprehensions evaluate differently?
正如您所说,0.1
已经不准确,因此乘以它并不完全等同于除以 10
(其中至少两个输入都是精确整数)。有时,这种不准确意味着结果与除以 10
不同;毕竟,你乘以“刚刚超过十分之一”,而不是“十分之一”。
此问题的部分内容已在别处解决(例如 is floating point math broken?)。
以下揭示了除法与乘法生成数字的方式不同:
>>> listd = [i/10 for i in range(6)]
>>> listm = [i*0.1 for i in range(6)]
>>> print(listd)
[0.0, 0.1, 0.2, 0.3, 0.4, 0.5]
>>> print(listm)
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5]
第二种情况,0.3的舍入误差约为1e-16,双精度浮点数。
但是我不明白关于输出的三件事:
- 既然这里唯一可以用二进制精确表示的数字是 0.0 和 0.5,为什么上面打印的不是唯一精确的数字?
- 为什么这两个列表理解的评估不同?
- 为什么数字的两个字符串表示不同,但二进制表示不同?
>>> def bf(x):
return bin(struct.unpack('@i',struct.pack('!f',float(x)))[0])
>>> x1 = 3/10
>>> x2 = 3*0.1
>>> print(repr(x1).ljust(20), "=", bf(x1))
>>> print(repr(x2).ljust(20), "=", bf(x2))
0.3 = -0b1100101011001100110011011000010
0.30000000000000004 = -0b1100101011001100110011011000010
这里的关键点是 10
是用二进制表示的,而 0.1
不是。除以 10 可以得到每个分数最接近的表示;乘以 0.1 的不精确转换并不能保证精度。有时您会“足够接近”以将结果四舍五入到一位小数,有时则不然。
这些理由够吗?
回答每个问题:
- Since the only numbers here exactly representable in binary are 0.0 and 0.5, why aren't those the only exact numbers printed above?
Python 将任何浮点数的显示四舍五入为计算时产生相同值的最短文字。所以是的,其中许多数字实际上与它们代表的实际数字并不相同,但如果你在 Python 中输入它们,你会在没有数学的情况下得到那个(稍微不准确的)值。
正如您所说,
- Why do the two list comprehensions evaluate differently?
0.1
已经不准确,因此乘以它并不完全等同于除以 10
(其中至少两个输入都是精确整数)。有时,这种不准确意味着结果与除以 10
不同;毕竟,你乘以“刚刚超过十分之一”,而不是“十分之一”。