浮点数是负零吗? (-0f)

时间:2011-02-23 19:25:13

标签: language-agnostic floating-point

IEEE浮点数有一个位用于指示符号,这意味着您可以在技术上具有零(+0和-0)的不同二进制表示。有没有我可以做的算术运算,例如在C中导致负零浮点值?

这个问题受到另一个人的启发,这让我们怀疑你是否可以使用0.0f安全地比较==,我还想知道是否还有其他方法来表示零会导致float1 == 0.0f为了看似完全平等的价值而打破。

[编辑]请不要评价比较花车的平等安全性!我并没有试图添加那些重复的问题。

10 个答案:

答案 0 :(得分:17)

根据标准,负零存在,但它等于正零。对于几乎所有目的,两者的行为方式相同,许多人认为负面的存在是一个实现细节。但是,有些函数的行为完全不同,即除法和atan2

#include <math.h>
#include <stdio.h>

int main() {
    double x = 0.0;
    double y = -0.0;
    printf("%.08f == %.08f: %d\n", x, y, x == y);
    printf("%.08f == %.08f: %d\n", 1 / x, 1 / y, 1 / x == 1 / y);
    printf("%.08f == %.08f: %d\n", atan2(x, y), atan2(y, y), atan2(x, y) == atan2(y, y));
}

此代码的结果是:

0.00000000 == -0.00000000: 1
1.#INF0000 == -1.#INF0000: 0
3.14159265 == -3.14159265: 0

这意味着代码可以正确处理某些限制而无需显式处理。不确定依靠此功能接近极限的值是一个好主意,因为简单的计算错误可能会改变符号并使值远远不正确,但如果您避免计算,您仍然可以利用它改变标志。

答案 1 :(得分:10)

  

是否有算术运算I.   例如可以在C中做出结果   在负零浮点   值?

不确定

float negativeZero = -10.0e-30f * 10.0e-30f;

乘法的数学精确结果不能表示为浮点值,因此它会舍入到最接近的可表示值,即-0.0f

负零的语义由IEEE-754标准明确定义;在算术表达式中,它的行为与零的行为不同的唯一真实可观察方式是,如果除以它,你将得到一个不同的无穷大符号。例如:

1.f /  0.f --> +infinity
1.f / -0.f --> -infinity

使用-0.f进行比较,加法和减法得到与+0.f相同的结果(在默认舍入模式下)。乘法可以保留零的符号,但如上所述,它通常是不可观察的。

一些数学库函数,其行为可能因零符号而异。例如:

copysignf(1.0f, 0.0f) -->  1.0f
copysignf(1.0f,-0.0f) --> -1.0f

这在复杂功能中更为常见:

csqrtf(-1.0f + 0.0f*i) --> 0.0f + 1.0f*i
csqrtf(-1.0f - 0.0f*i) --> 0.0f - 1.0f*i

但是,一般情况下,您不必担心负零。

答案 2 :(得分:7)

是零可以签名,但标准要求正零和负零测试等于

答案 3 :(得分:3)

有几个简单的算术运算导致零回答(至少在我测试过的i386 / x64 / ARMv7 / ARMv8系统上):

  • -1 * 0
  • 0 / -1

当我编写一个优化算术表达式的优化器时,这些让我感到意外。如果b恰好是负数,则将“ a = b * 0 ”优化为“ a = 0 ”将导致错误答案(+0)(正确答案为-0 )。

答案 4 :(得分:2)

是的,float does有一个负零,但是no,在比较浮点值时你不必担心这个。

浮点运算被定义为在特殊情况下正常工作。

答案 5 :(得分:1)

是的,float的负值为零,就像其他IEEE浮点类型一样,如double(在具有IEEE浮点的系统上)。 Octave中有一个如何创建它们的例子here;相同的操作在C中工作。==运算符将+0和-0视为相同,因此负零不会破坏该类型的比较。

答案 6 :(得分:1)

是的,您可以拥有+0和-0,这些是不同的位模式(应该通过相等测试失败)。你永远不应该使用== with float,当然不是IEEE float。 &LT;或者&gt;没事。关于这个主题还有很多其他的SO问题和讨论,所以我不会在这里讨论它。

答案 7 :(得分:0)

这个float1 == 0.0f从来就不是一个安全的比较。

如果您有类似

的内容
float x = 0.0f;
for (int i = 0; i < 10; i++) x += 0.1f;
x -= 1.0f;
assert (x == 0.0f);

即使它看起来应该是0,它也会失败。

答案 8 :(得分:0)

使用浮点数进行相等比较时应谨慎。请记住,您试图在二进制系统中表示十进制值。

Is it safe to check floating point values for equality to 0?

如果你必须比较浮点值,我建议你使用某种你可以接受的容差float1 <= toleranceVal && float1 >= toleranceVal2或乘以10的因子并作为整数转换。 if (!(int)(float1 * 10000)) { .. some stuff .. }

答案 9 :(得分:0)

-lm有signbit()函数可用于指示值是否为负数(包括-0)