为什么 python print() 打印一个舍入值而不是不可表示的浮点数的精确值
Why python print() prints a rounded value rather than the exact value for non-representable float
值 0.1
不能表示为 64 位浮点数。
准确值大致等于0.10000000000000000555
https://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/
您可以使用以下简单代码突出显示此行为:
timestep = 0.1
iterations = 1_000_000
total = 0
for _ in range(iterations):
total += timestep
print(total - timestep * iterations) # output is not zero but 1.3328826753422618e-06
我完全理解为什么 0.1
不能表示为 float 64 的精确值,但我不明白的是为什么当我做 print(0.1)
时,它输出 0.1
而不是作为浮点数 64 的基础值。
当然,基础值在以 10 为基数的系统中有更多的数字,因此应该涉及一些舍入,但我正在寻找所有值的规范以及如何控制它。
我遇到了一些应用程序在数据库中存储数据的问题:
- python 应用程序(使用
str(0.1)
)将显示 0.1
- 另一个数据库客户端 UI 将显示
0.10000000000000000555
,这将让最终用户失望
P-S:我对其他值有其他问题
此致,
首先,你是对的,浮点数(单数,双数,等等)都有一个精确的值。
对于 64 位 IEEE-754 双精度数,最接近 0.1 的可表示值恰好是 0.1000000000000000055511151231257827021181583404541015625
,如您所见,相当长。但是可表示的浮点值都有有限的小数位数,因为基数 (2) 是 10 的某个幂的除数。
对于像 python 这样的 REPL 语言,属性:
是必不可少的
- 浮点数的打印表示应重新解释为相同的值
一个结果是
- 每两个不同的浮点数应该有不同的印刷表示
要获得这些属性,有几种可能性:
- 打印准确的值。这可能是很多数字,对于绝大多数人来说,只是噪音。
- 打印足够多的数字,以便每两个不同的浮点数具有不同的表示形式。对于双精度,在最坏的情况下是 17 位数字。因此,表示浮点值的简单实现是始终打印 17 位有效数字。
- 打印最短的表示,将被重新解释不变。
Python,许多其他语言都选择了第三种解决方案,因为当用户输入 0.1
时打印 0.10000000000000001
被认为很烦人。人类用户通常选择较短的表示,打印的表示供人类使用。越短越好
不好的 属性 是它可能给人一种错误的印象,即那些浮点值存储的是精确的十进制值,如 1/10。这是现在在这里和许多地方传播的知识。
值 0.1
不能表示为 64 位浮点数。
准确值大致等于0.10000000000000000555
https://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/
您可以使用以下简单代码突出显示此行为:
timestep = 0.1
iterations = 1_000_000
total = 0
for _ in range(iterations):
total += timestep
print(total - timestep * iterations) # output is not zero but 1.3328826753422618e-06
我完全理解为什么 0.1
不能表示为 float 64 的精确值,但我不明白的是为什么当我做 print(0.1)
时,它输出 0.1
而不是作为浮点数 64 的基础值。
当然,基础值在以 10 为基数的系统中有更多的数字,因此应该涉及一些舍入,但我正在寻找所有值的规范以及如何控制它。
我遇到了一些应用程序在数据库中存储数据的问题:
- python 应用程序(使用
str(0.1)
)将显示0.1
- 另一个数据库客户端 UI 将显示
0.10000000000000000555
,这将让最终用户失望
P-S:我对其他值有其他问题
此致,
首先,你是对的,浮点数(单数,双数,等等)都有一个精确的值。
对于 64 位 IEEE-754 双精度数,最接近 0.1 的可表示值恰好是 0.1000000000000000055511151231257827021181583404541015625
,如您所见,相当长。但是可表示的浮点值都有有限的小数位数,因为基数 (2) 是 10 的某个幂的除数。
对于像 python 这样的 REPL 语言,属性:
是必不可少的- 浮点数的打印表示应重新解释为相同的值
一个结果是
- 每两个不同的浮点数应该有不同的印刷表示
要获得这些属性,有几种可能性:
- 打印准确的值。这可能是很多数字,对于绝大多数人来说,只是噪音。
- 打印足够多的数字,以便每两个不同的浮点数具有不同的表示形式。对于双精度,在最坏的情况下是 17 位数字。因此,表示浮点值的简单实现是始终打印 17 位有效数字。
- 打印最短的表示,将被重新解释不变。
Python,许多其他语言都选择了第三种解决方案,因为当用户输入 0.1
时打印 0.10000000000000001
被认为很烦人。人类用户通常选择较短的表示,打印的表示供人类使用。越短越好
不好的 属性 是它可能给人一种错误的印象,即那些浮点值存储的是精确的十进制值,如 1/10。这是现在在这里和许多地方传播的知识。