3

早上好,

我正在从 FITS 文件中读取两个数字(表示单个数字的整数和浮点部分),将它们转换为长双精度数(在我的机器中为 128 位),然后将它们相加。

结果并不像使用 128 位浮点数所期望的那样精确。这是代码:

a_int = np.longdouble(read_header_key(fits_file, 'I'))
print "I %.25f" % a_int, type(a_int)
a_float = np.longdouble(read_header_key(fits_file, 'F'))
print "F %.25f" % a_float, a_float.dtype
a = a_int + a_float
print "TOT %.25f" % a, a.dtype

这是我得到的答案:

I 55197.0000000000000000000000000 <type 'numpy.float128'>
F 0.0007660185200000000195833 float128
TOT 55197.0007660185219720005989075 float128

结果与我所期望的(55197.0007660185200000000195833)相差11个十进制数字(总共16个有效数字)。我希望 128 位浮点数的精度更高。我究竟做错了什么?

此结果在 Mac 机器和 Linux 32 位机器上重现(在这种情况下,dtype 为 float96,但值完全相同)

在此先感谢您的帮助!

马泰奥

4

2 回答 2

3

我的猜测是%f修饰符从您的 longdouble 对象构造一个浮点数,并在创建格式字符串时使用它。

>>> import numpy as np
>>> np.longdouble(55197)
55197.0
>>> a = np.longdouble(55197)
>>> b = np.longdouble(0.0007660185200000000195833)
>>> a
55197.0
>>> b
0.00076601852000000001958
>>> a + b
55197.00076601852
>>> type(a+b)
<type 'numpy.float128'>
>>> a + b == 55197.00076601852
False

作为旁注,甚至repr没有打印足够的数字来重建对象。这仅仅是因为你不能有一个足以传递给你的浮点文字longdouble

于 2013-02-14T13:50:17.460 回答
3

问题在于您打印的np.longdouble. 当您使用 格式化时%f,Python 在打印之前将结果转换为浮点数(64 位)。

这里:

>>> a_int = np.longdouble(55197)
>>> a_float = np.longdouble(76601852) / 10**11
>>> b = a_int + a_float
>>> '%.25f' % b
'55197.0007660185219720005989075'
>>> '%.25f' % float(b)
'55197.0007660185219720005989075'
>>> b * 10**18
5.5197000766018519998e+22

longdouble请注意,在我的机器上,与普通double(小数点后 20 位而不是 15 位)相比,我只获得了更高的精度。因此,可能值得看看该Decimal模块是否更适合您的应用程序。Decimal处理任意精度的十进制浮点数而不会损失精度。

于 2013-02-14T13:52:21.590 回答