numpy 打印16位最小浮点数看起来不一致?

33qvvth1  于 2022-12-13  发布在  其他
关注(0)|答案(2)|浏览(296)

有人能解释一下为什么打印float16 minimal会产生下面不同的结果吗?是设计使然还是一个bug?

In [87]: x=np.finfo(np.float16).min
    
    In [88]: x_array_single=np.array([x])
    
    In [89]: x
    Out[89]: -65500.0
    
    In [90]: x_array_single
    Out[90]: array([-65504.], dtype=float16)
hm2xizp9

hm2xizp91#

编辑:

请注意,如果打印数组的第一个值,也会出现此问题:

>>> x_array[0]
-65500.0

在NumPy 1.14.0发行说明中,已写入:
浮点数组和标量使用一种新的十进制表示算法,给出最短的唯一表示。这通常会缩短float16小数输出,有时会缩短float32和float128输出。float64应该不受影响。请参阅np.set_printoptions的新floatmode选项。
这就是输出不同的原因。
当你把它打印成float32或float64(或者只是使用内置的64位浮点格式)时,你会得到更精确的输出:

>>> float(x)
-65504.0

>>> np.float32('-65504')
-65504.0

以及:

>>> float(x_array[0])
-65504.0

您还可以在此处看到精度的变化:

>>> np.float16('65500') == np.float16('65504')`
True

>>> np.float32('65500') == np.float32('65504')
False
w6lpcovy

w6lpcovy2#

在-65500的fp 16中,内部表示为字节255和251。请参见

import struct
struct.unpack('BB', struct.pack('e', -65500))
# (255, 251)

-65504的内部表示也是如此

import struct
struct.unpack('BB', struct.pack('e', -65504))
# (255, 251)

在二进制中,考虑到我的机器是小尾序(所以,它应该读为251,然后255),也就是说
符号为-,指数为30-15=15,然后是1(隐式)+1 /2 +1/4+...+/1024十位=

- (2**15) * (1.0 + sum(1/2**k for k in range(1,11)))

-65504(仅声明,浮点表示是一门精确的科学;- ))
下一个可能的指数是
其值为

struct.unpack('e', b'\xfe\xfb')

-65472
-65504和-65472之间的中点是-65488。您可以看到,所有小于-65488的数字都与-65504共享相同的fp 16表示。而所有大于-65488的数字则不共享。

struct.unpack('BB', struct.pack('e', -65488.01))
# (255,251)
struct.unpack('BB', struct.pack('e', -65488))
# (254, 251)

或者使用nokla的方法(当我输入这个方法时,他的答案出现了)

np.float16(-65488.01)==np.float16(-65504)
# True
np.float16(-65488)==np.float16(-65504)
# False

至于你最初的问题(我意识到nokla和我都回答了“为什么它不是一个错误”,或“为什么它是可能的”,但不是真正的“为什么它是这样的”),嗯,我猜一些显示(并且只显示。从值的Angular 来看,所有的都是同一件事)当在许多等价的小数表示法中有一个选择时,倾向于“最圆”的小数表示法,而另一些人则倾向于最核心的价值:-65500.0是以字节(255,251)表示的所有值中最接近的十进制值。而-65504是以这些字节表示的所有值的平均值。

相关问题