如何在C中将负零转换为正零?

时间:2012-03-11 19:07:00

标签: c floating-point

您好,我正在学习Objective C,而我正在做经典的计算器示例。

问题是,当我将零乘以任何负数时,我得到负零,并且我将结果放入(双)类型!

为了看看发生了什么,我玩了调试器,这就是我得到的:

  

(gdb)print -2 * 0
  $ 1 = 0

     

(gdb)print(double)-2 * 0
  $ 2 = -0

在第二种情况下,当我将其转换为双重类型时,它变为负零!如何在我的应用程序中修复它?我需要和双打一起工作。 如何修复结果,以便在结果为零时得到零?

5 个答案:

答案 0 :(得分:13)

我做了一个简单的测试:

double d = (double) -2.0 * 0;

if (d < 0)
    printf("d is less than zero\n");
if (d == 0)
    printf("d is equal to zero\n");
if (d > 0)
    printf("d is greater than zero\n");

printf("d is: %lf\n", d);

输出:

  

d等于零
  d是:-0.000000

因此,要解决此问题,您可以向应用程序添加简单的if-check:

if (d == 0) d = 0;

答案 1 :(得分:5)

http://en.wikipedia.org/wiki/Signed_zero

  

数字0通常编码为+0,但可以用+0或-0

表示

它不应该影响计算或UI输出。

答案 2 :(得分:3)

这里存在关于运算符优先级的误解:

(double) -2 * 0

被解析为

((double)(-(2))) * 0

(-2.0) * 0.0基本相同。

C标准信息附件J列为非指定行为某些运算符是否可以生成负零,以及当存储在对象中时负零是否变为正常零( >

相反,(double)(-2 * 0)应该在大多数当前平台上生成正零0.0,因为乘法是使用整数运算执行的。 C标准确实支持区分正负零整数的架构,但现在这些架构很少见。

如果你想强制零是积极的,这个简单的修复应该有效:

if (d == 0) {
    d = 0;
}

您可以通过以下方式使意图更清晰:

if (d == -0.0) {
    d = +0.0;
}

但如果d为正零,测试也会成功。

Chux为符合IEC 60559标准的环境提供了更简单的解决方案:

d = d + 0.0;  // turn -0.0 to +0.0

答案 3 :(得分:2)

  

如何在我的应用程序中解决这个问题?

代码确实没有被破坏,因此无需修复&#34;。 @kennytm

  

如何修复结果,以便在结果为零时得到零?

要在结果为-时轻松摆脱-0.0,请添加0.0。遵循标准(IEC 60559浮点)规则的代码将产生-符号。

double nzero = -0.0;
printf("%f\n", nzero);
printf("%f\n", nzero + 0.0);

printf("%f\n", fabs(nzero));  // This has a side effect of changing all negative values

// pedantic code using <math.h>
if (signbit(nzero)) nzero = 0.0; // This has a side effect of changing all negative values
printf("%f\n", nzero);

常用输出。

-0.000000
0.000000
0.000000
0.000000

然而,对于可能具有任何价值的一般double x,很难击败以下内容。 @Richard J. Ross III @chqrlie x + 0.0方法的优势在于可能不会引入分支,但以下内容很明确。

if (x == 0.0) x = 0.0;

注意:fmax(-0.0, 0.0)可能会产生-0.0。

答案 4 :(得分:0)

在我的代码中(在C MPI intel编译器上)-0.0+0.0不相同。

例如:

d = -0.0
if (d < 0.0)
    do something...

它正在做这个“事情”。

还要添加-0.0 + 0.0 = -0.0...