numpy.float96的奇怪行为
我漏掉了什么:
In [66]: import numpy as np
In [67]: np.float(7.0 / 8)
Out[67]: 0.875 #OK
In [68]: np.float32(7.0 / 8)
Out[68]: 0.875 #OK
In [69]: np.float96(7.0 / 8)
Out[69]: -2.6815615859885194e+154 #WTF
In [70]: sys.version
Out[70]: '2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)]'
编辑。 在cygwin上,上面的代码运行得很好:
$ python
Python 2.5.2 (r252:60911, Dec 2 2008, 09:26:14)
[GCC 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.float(7.0 / 8)
0.875
>>> np.float96(7.0 / 8)
0.875
为了完整性,我在普通的python中检查了这段代码(不是在Ipython中):
C:\temp>python
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.float(7.0 / 8)
0.875
>>> np.float96(7.0 / 8)
-2.6815615859885194e+154
>>>
编辑
我在Numpy的bug跟踪网站上看到三个错误报告(976,902,和884),但这个似乎和字符串表示没有关系。因此我开了一个新的bug(1263)。会在这里更新进展情况
3 个回答
在1.3.0版本中,针对Windows系统的长双精度格式化问题进行了一些修复。具体的修复内容可以查看以下链接:http://projects.scipy.org/numpy/changeset/6219、http://projects.scipy.org/numpy/changeset/6218、http://projects.scipy.org/numpy/changeset/6217
这个问题是因为mingw编译器(官方numpy二进制文件使用的编译器)和微软的运行时(printf函数来自的地方)之间不兼容造成的。
微软的编译器把long double和double看作是一样的类型,微软的C运行时(包括printf)也是这样认为的。而mingw编译器出于某种原因,把long double定义得足够大,可以存储80位的高精度数字,但微软的printf并不知道这一点,所以它无法正确打印long double。
我们通过使用自己的格式化函数解决了一些问题,但我认为真正的解决办法是强制在使用mingw编译时,把long double当作double来处理。我想这个会在numpy 1.5.0版本中实现。
这对我来说运行得很好:
In [1]: import numpy as np
In [2]: np.float(7.0/8)
Out[2]: 0.875
In [3]: np.float96(7.0/8)
Out[3]: 0.875
你用的是什么版本的Numpy?我用的是Python 2.6.2和Numpy 1.3.0,系统是64位的Vista。
我在另一台电脑上试了同样的东西,那台电脑是32位的XP,使用的是Python 2.5.2和Numpy 1.2.1,结果让我很惊讶,我得到了:
In [2]: np.float96(7.0/8)
Out[2]: -2.6815615859885194e+154
经过一些调查,我在32位XP上安装了Python 2.6.3和Numpy 1.3.0,发现:
In [2]: np.float96(7.0/8)
Out[2]: 0.875
所以这肯定是旧版本的Numpy或者旧版本的Python中的一个bug……