gpt4 book ai didi

python - float 打印不一致。为什么它有时会起作用?

转载 作者:太空宇宙 更新时间:2023-11-04 09:31:08 26 4
gpt4 key购买 nike

使用以下(几乎是最小的)示例:

import numpy as np
for x in np.arange(0,2,0.1):
print(x)

我们得到:

0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6000000000000001
0.7000000000000001
0.8
0.9
1.0
1.1
1.2000000000000002
1.3
1.4000000000000001
1.5
1.6
1.7000000000000002
1.8
1.9000000000000001

作为输出。

我知道 X.X000001 输出应该归咎于“ float 精度问题”,但我不明白为什么它有时会起作用。显然 0.3 不能用 float 以 2 为底数精确表示,而且我没有看到数字中没有仅用一位小数显示的任何模式。

Python 怎么知道 0.1 足以显示数字?什么样的魔法告诉它截断剩余的数字?为什么它只是有时有效?

最佳答案

您正在打印 numpy.float64 对象,而不是 Python 内置的 float 类型,它使用 David Gay's dtoa algorithm .

截至version 1.14 , numpy 使用 dragon4 algorithm to print floating point values , 调整为接近与用于 Python float 类型的 David Gay 算法相同的输出:

Numpy scalars use the dragon4 algorithm in "unique" mode (see below) for str/repr, in a way that tries to match python float output.

numpy.format_float_positional() function对此进行更详细的记录:

unique : boolean, optional

If True, use a digit-generation strategy which gives the shortest representation which uniquely identifies the floating-point number from other values of the same type, by judicious rounding. If precision was omitted, print out all necessary digits, otherwise digit generation is cut off after precision digits and the remaining value is rounded.

因此 0.2 可以通过仅打印 0.2 来唯一地呈现,但是系列中的下一个值 (0.30000000000000004) 不能,你必须包含额外的数字以唯一地表示确切的值。

如何实际上非常复杂;您可以在 Bungie 的 Destiny 游戏工程师 Ryan Juckett 的 Printing Floating-Point Numbers series 中阅读关于此的完整报告。 .

但基本上,输出字符串的代码需要确定所有围绕可能的 float 聚类的十进制数字的最短表示形式,这些数字不能被解释为下一个或之前的可能 float :

floating point number line for 0.1, with the next and previous possible float values and possible representations

本图来自The Shortest Decimal String That Round-Trips: Examples通过 Rick Regan ,其中也涵盖了其他一些情况。 蓝色 中的数字是可能的 float64 值,绿色 中的数字是十进制数的可能表示形式。请注意灰色的中点标记,任何适合围绕浮点值的两个中点之间的表示都是公平游戏,因为所有这些表示都会产生相同的值。

David Gay 和 Dragon4 算法的目标都是找到能够再次产生完全相同的浮点值的最短十进制字符串输出。来自Python 3.1 What's New section on the David Gay approach :

Python now uses David Gay’s algorithm for finding the shortest floating point representation that doesn’t change its value. This should help mitigate some of the confusion surrounding binary floating point numbers.

The significance is easily seen with a number like 1.1 which does not have an exact equivalent in binary floating point. Since there is no exact equivalent, an expression like float('1.1') evaluates to the nearest representable value which is 0x1.199999999999ap+0 in hex or 1.100000000000000088817841970012523233890533447265625 in decimal. That nearest value was and still is used in subsequent floating point calculations.

What is new is how the number gets displayed. Formerly, Python used a simple approach. The value of repr(1.1) was computed as format(1.1, '.17g') which evaluated to '1.1000000000000001'. The advantage of using 17 digits was that it relied on IEEE-754 guarantees to assure that eval(repr(1.1)) would round-trip exactly to its original value. The disadvantage is that many people found the output to be confusing (mistaking intrinsic limitations of binary floating point representation as being a problem with Python itself).

The new algorithm for repr(1.1) is smarter and returns '1.1'. Effectively, it searches all equivalent string representations (ones that get stored with the same underlying float value) and returns the shortest representation.

The new algorithm tends to emit cleaner representations when possible, but it does not change the underlying values. So, it is still the case that 1.1 + 2.2 != 3.3 even though the representations may suggest otherwise.

关于python - float 打印不一致。为什么它有时会起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55727214/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com