从float32转换为float时如何保持精度?

时间:2017-01-31 20:49:08

标签: python python-2.7 numpy

我有一个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。我需要保留数据的原生精度。

2 个答案:

答案 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中)。碰巧的是,在舍入时,它与您在代码中键入的文本完全匹配。因此,它具有完全相同的值。