我有一个numpy.float32
对象,我想编码为JSON。问题是,当我转换为本机python float
时,我会失去该值的精确度。
示例:
In [1]: import numpy as np
In [4]: np.float32(295.96).item()
Out[4]: 295.9599914550781
但是,如果我先转换为字符串,然后浮动,则保留精度。
In [3]: float(str(np.float32(295.96)))
Out[3]: 295.96
有没有办法保留我的精确度,而不必先通过字符串?
为什么str(np.float32(295.96))
似乎保留了精确度,但np.float32(295.96).item()
(或float(np.float32(295.96))
或np.asscalar(np.float32(295.96))
)却没有?
注意:我不能假设精度始终为.01
。我需要保留数据的原生精度。
答案 0 :(得分:2)
你错误地认为你在控制台中看到的是真正发生的事情。您看到的结果(即舍入)仅适合您=查看控制台的人。这就是不幸地实现浮标印刷的方式(IMO令人困惑)。
底层浮动总是正确的,例如
In [4]: a = np.float32(295.96)
In [5]: a
Out[5]: 295.95999
In [6]: import json
In [7]: json.dumps(a.item())
Out[7]: '295.9599914550781'
答案 1 :(得分:2)
无法在32位值中存储64位精度。在python中,float
是64位(在C中称为double
)。作为演示,64位浮点数一切正常:
>>> d = 295.6; dn = np.float64(d)
>>> (d, dn)
(295.6, 295.95999999999998) # numpy prints out more digits than python
>>> d == dn # but these are still the same
True
>>> d - dn
0.0
但是如果尝试使用32位,则会降低精度
>>> d = 295.96; fn = np.float32(d)
>>> (d, fn)
(295.96, 295.95999)
>>> d == fn
False
>>> d - fn
8.5449218545363692e-06
为什么str(np.float32(295.96))似乎保持精度
str(np.float32(295.96))
看起来保留了精确度,因为np.float32.__str__
为了方便起见(在基数10中)。碰巧的是,在舍入时,它与您在代码中键入的文本完全匹配。因此,它具有完全相同的值。