C: 一个double值如果等于-0是什么意思?

7

我刚才在使用gdb打印一个double类型的值时,惊讶地看到它打印出了-0。

在C语言中,什么是-0的double值?

顺便说一下,当我用0进行比较时,返回了true:我只需执行以下操作进行比较:

在gdb中

> print some_double
-0
> print some_double == 0
1
3个回答

16

负零是数值计算中一个有用的概念,在C语言中也是一个有效的浮点数。


3
这是一个关于printf的众所周知的问题。由于您使用的是浮点数,因此在二进制中可能不存在一种表示方式。大多数情况下,二进制表示并不完美,因此0有时被存储为0.00000000000000...0042,有时则被存储为-0.000000000000000000000123。当printf打印第二个值时,您会得到奇怪的-0。
我不太清楚您如何与0进行比较,但请记住,在进行浮点数比较时,请添加一个epsilon以调整奇异性。例如:要测试两个浮点数是否相等,请勿编写a == b,而是编写fabs(a-b) < 1e-13,其中1e-13是epsilon(选择适合您的指数)。

你认为gdb是printf的打印语句吗? - hhafez
3
许多数字都有IEEE 754浮点表示法中的“完美”表示,包括0和-0。 - bk1e
1
为什么应该将-0.000000000000000000000123打印为-0?正如bk1e所说,浮点数中的0和-0是完全可表示的,不需要任何舍入。 - Joachim Sauer
@saua:那不是四舍五入,而是所容忍的误差。 - dirkgently
2
我并不反对模糊比较。但是说0被表示为一个不是0的值是误导性的,因为0可以被精确地表示。如果原帖中的变量“some_double”包含-1.23e-22,“print some_double == 0”将打印“0”,而不是“1”。-1.23e-22不是0。 - bk1e
显示剩余3条评论

2
实际上,在第四章中,作者在书籍《写出优秀的代码,卷1》中清楚地给出了答案,这是因为在IEEE FP标准中使用1的补码来表示有符号浮点数。他说:
尾数使用的是一种补码格式,而不是二进制补码。这意味着尾数的24位值仅是一个无符号二进制数,而符号位,在位31上,决定该值是正还是负。一的补码数字具有非常特殊的属性,即存在两个零的表示方式(符号位设置或清除)。通常,这只对设计浮点软件或硬件系统的人很重要。
重点是我的。

IEEE浮点数使用符号和值(以及指数),而不是补码。 (此外,分数是有效数字,而不是尾数。) - Eric Postpischil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接