为什么 python print() 打印一个舍入值而不是不可表示的浮点数的精确值

发布于 2025-01-09 13:49:02 字数 1000 浏览 1 评论 0原文

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 而不是作为 float 64 的基础值。

当然,基础值在以 10 为基数的系统上有更多的数字,因此应该涉及一些舍入,但我正在寻找所有的规范值以及如何控制它。

我遇到了一些应用程序在数据库中存储数据的问题:

  • python 应用程序(使用 str(0.1))将显示 0.1
  • 另一个数据库客户端 UI 将显示 0.10000000000000000555< /code>,这会让最终用户感到困惑

P-S:我对其他值有其他问题

问候,

The value 0.1 is not representable as a 64 bits floats.
The exact value is roughly equals to 0.10000000000000000555

https://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/

You can highlight this behavior with this simple code:

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

I totally understand why 0.1 is not representable as an exact value as a float 64, but what I don't get is why when I do print(0.1), it outputs 0.1 and not the underlying value as a float 64.

Of course, the underlying value has many more digits on a base 10 system so there should be some rounding involved, but I am looking for the specification for all values and how to control that.

I had the issue with some application storing data in database:

  • the python app (using str(0.1)) would show 0.1
  • another database client UI would show 0.10000000000000000555, which would throw off the end user

P-S: I had other issues with other values

Regards,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

软甜啾 2025-01-16 13:49:02

首先,你是对的,浮点数(单浮点数、双浮点数等)具有精确的值。

对于 64 位 IEEE-754 双精度,最接近 0.1 的可表示值将恰好是 0.1000000000000000055511151231257827021181583404541015625,如您所见,相当长。但可表示的浮点值都具有有限数量的十进制数字,因为基数 (2) 是 10 的某个幂的除数。

对于像 python 这样的 REPL 语言,必须具有以下属性:

  • 浮点数的打印表示形式应被重新解释为相同的值

结果是

  • 每两个不同的浮点数应具有不同的打印表示形式

为了获得这些属性,有几种可能性:

  • 打印确切的值。这可能是很多数字,而对于绝大多数人来说,这只是噪音。
  • 打印足够的数字,以便每两个不同的浮点数有不同的表示。对于双精度,最坏情况下为 17 位。因此,表示浮点值的简单实现是始终打印 17 位有效数字。
  • 打印将被重新解释不变的最短表示。

Python 和许多其他语言选择了第三种解决方案,因为当用户输入 0.1 时打印 0.100000000000000001 被认为很烦人。人类用户通常选择较短的表示形式,而打印的表示形式供人类消费。越短越好。

不好的特性是,它可能会给人一种错误的印象,即这些浮点值存储的是精确的十进制值,例如 1/10。现在这里和许多地方都在传播这种知识。

First, you are right, floats (single, double, whatever) have an exact value.

For 64 bits IEEE-754 double, the nearest representable value to 0.1 would be exactly 0.1000000000000000055511151231257827021181583404541015625, quite long as you can see. But representable floating point values all have a finite number of decimal digits, because the base (2) is a divisor of some power of 10.

For a REPL language like python, it is essential to have this property:

  • the printed representation of the float shall be reinterpreted as the same value

A consequence is that

  • every two different float shall have different printed representation

For obtaining those properties, there are several possbilities:

  • print the exact value. That can be many digits, and for the vast majority of humans, just noise.
  • print enough digits so that every two different float have a different representation. For double precision, that's 17 digits in the worse case. So a naive implementation for representing floating point values would be to always print 17 significant digits.
  • print the shortest representation that would be reinterpreted unchanged.

Python, and many other languages have chosen the 3rd solution, because it is considered annoying to print 0.10000000000000001 when user have entered 0.1. Human users generally choose the shorter representation and printed representation is for human consumption. The shorter, the better.

The bad property is that it could give the false impression that those floating point values are storing exact decimal values like 1/10. That's a knowledge that is evangelized here and in many places now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文