2014-11-05 298 views
5

我可能会错过一些基本的东西,但考虑到这个解释器会话:为什么-0.0和0.0不一样?

>>> -0.0 is 0.0 
False 
>>> 0.0 is 0.0 
True 
>>> -0.0 # The sign is even retained in the output. Why? 
-0.0 
>>> 

你会认为,Python解释器会意识到-0.00.0是相同的数字。事实上,他们比较为等于:

>>> -0.0 == 0.0 
True 
>>> 

那么,为什么Python的两个之间的区别,并生成-0.0一个全新的对象?它不整数做到这一点:

>>> -0 is 0 
True 
>>> -0 # Sign is not retained 
0 
>>> 

现在,我意识到,浮点数是一个巨大的与计算机上的问题来源,但这些问题总是针对其准确性。例如:

>>> 1.3 + 0.1 
1.4000000000000001 
>>> 

但是,这不是一个准确性问题,是吗?我的意思是,我们正在谈论这里的数字的符号,而不是小数点。


我可以重现这一行为在这两个的Python 2.7和Python 3.4,所以这不是一个特定版本的问题。

+1

我相信这是IEEE 754浮点表示的一个特性,这意味着它不是特定于Python。 – 2014-11-05 19:04:41

+0

整数溢出可能是更严重的“计算机问题的根源”。 – tmyklebu 2014-11-05 22:35:44

+0

为什么你使用'is'进行数字比较?您的许多问题与签名的零无关:尝试'x = 2.3','y = 2.3',接着'x是y'。然后,为了好玩,试试'x = 2.3; y = 2.3'(全部在一行上),后面是'x是y'。 – 2014-11-06 12:21:28

回答

11

在IEEE754中,浮点数的格式,符号是一个单独的位。所以-0.0和0.0有所不同。 整数使用二进制补码来表示负数;这就是为什么只有一个0

使用is只有你真的想比较对象的实例。否则,特别是对号码,使用==

>>> 1999+1 is 2000 
False 

>>> 0.0 == -0.0 
True 
+0

我接受你的答案,因为你解释了浮动情况以及整数。但是,你能想到任何真实世界的'-0.0'用例吗?我知道它有一些理论上的用途,但它似乎只是阻碍了它的发展。 – iCodez 2014-11-05 19:30:38

+7

@iCodez:带符号的零有助于实现复杂的数学函数。规范文件是:William Kahan,复杂基本函数的分支切割,或者关于Nothing的符号位。在:数值分析的艺术状态,克拉伦登出版社,牛津,1987年。在线副本很容易通过Google Scholar找到。 – njuffa 2014-11-05 19:50:46

+0

请注意,Python没有特别强制IEEE-754。 [参考](https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy)说:“这些代表机器级双精度浮点数。你受制于底层的机器体系结构(以及C或Java实现)用于可接受的范围和处理溢出。“但是在大多数平台和实现中,这意味着IEEE-754双打或者非常接近它。 – abarnert 2014-11-05 20:35:49

4

因为这两个数字的二进制表示是不同的。在0.0中,第32位为0,在-0.0中第32位为1.

+1

python中的浮点数是64位。 – Daniel 2014-11-05 19:11:39

+0

好的。答案仍然大致相同。浮点中的最后一位是符号位。正值1表示负值。 – 2014-11-05 19:18:06

+0

实际上,在2.x中,Python中的浮点数一般未指定,并且在CPython中指定为“用于构建解释器的C编译器中的任何”double“。 3。x,他们对它进行了一些清理,并在实现中将它们指定为“一台机器”double“”,但请注意“您受制于底层机器体系结构(以及C或Java实现)”。 – abarnert 2014-11-05 19:58:49

8

的IEEE标准浮点运算(IEEE 754)定义的signed zeroes列入。理论上它们允许您区分负数下溢和正数underflow

就python而言,使用==而不是is来比较数字。