Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C中把负零转换成正零?_C_Floating Point - Fatal编程技术网

如何在C中把负零转换成正零?

如何在C中把负零转换成正零?,c,floating-point,C,Floating Point,您好,我正在学习Objective C,我正在做经典的计算器示例 问题是,当我将零乘以任何负数时,得到的是一个负零,并且我将结果放入(双精度)类型中 为了查看发生了什么,我使用了调试器,得到了以下结果: (gdb)打印-2*0 $1=0 (gdb)打印(双)-2*0 $2=-0 在第二种情况下,当我将其转换为双精度类型时,它将变成负零!如何在我的应用程序中修复该问题?我需要和替身一起工作。 如何修正结果,以便在结果应为零时得到零?我做了一个简单的测试: double d = (double) -

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

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

为了查看发生了什么,我使用了调试器,得到了以下结果:

(gdb)打印-2*0
$1=0

(gdb)打印(双)-2*0
$2=-0

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

我做了一个简单的测试:

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);

数字0通常编码为+0,但可以用+0或+0表示−0


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

这里对运算符优先级存在误解:

(double) -2 * 0
被解析为

((double)(-(2))) * 0
基本上与
(-2.0)*0.0
相同

C标准资料性附录J将某些运算符是否会生成负零以及负零存储在对象中时是否会变为正常零列为非特定行为(6.2.6.2)

相反,在大多数当前平台上,
(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
如何在我的应用程序中修复该问题

代码确实没有被破坏,所以没有什么需要“修复”

当结果应该为零时,如何修正结果以得到零

要在结果为
-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);
然而,对于可能有任何价值的普通
双x
,很难击败以下因素。
x+0.0
方法有一个优点,即可能不会引入分支,但以下几点很清楚

if (x == 0.0) x = 0.0;
注意:
fmax(-0.0,0.0)
可能产生-0.0。

在我的代码中(在C MPI英特尔编译器上)
-0.0
+0.0
是不同的

例如:

d = -0.0
if (d < 0.0)
    do something...
d=-0.0
如果(d<0.0)
做点什么。。。
它正在做这件“事情”



同时添加
-0.0+0.0=-0.0…

结果是正确的。负零有什么问题?可能你的应用程序没有在GDB中运行。当然,您将控制输出的格式。此外,这个问题:“我如何修正结果,以便在结果应该为零时得到零?”基于一个不正确的前提——您得到了零。谢天谢地,
-0.0==+0.0
,所以您的问题消失了。@Jiminion这不是一个小故障-0.0的作用与+0.0的作用不同-
atan2()
是一种常见情况。虽然它们代表相同的值,-0.0的各个方面都依赖于实现(如果遵循IEEE标准,则不依赖于实现)。@Jiminion:IEEE浮点规范是非常值得尊敬的工作。其中的所有内容都是经过精心设计的,有些C编译器没有完全实现其中的所有细节和规定,这真是太糟糕了。
0.0
-0.0
之间的主要区别在于它们作为商值的行为:
1/0.0
是一个正无穷大,而
1/-0.0
是一个负无穷大,这是一个截然不同的东西。或者,如果你有一个C99实现(
if(signbit(d))d*=-1;
if(d==0)d=0。。。至少在VisualStudio2008上并不总是有效。@ThomasEding当然,非标准编译器会做非标准的事情。似乎它们违反了IEEE浮点标准。@ThomasEding
double x=-0.0;如果(x==0.0){x=0.0;}char buf[100];sprintf(buf,“d是:%lf\n”,x)和VS2008有效。也许您设置/查看
d
的方式有误;在您的电脑上进行测试并不能保证一般情况下
-0.0
会在某些情况下影响数值计算:如果您将其打印出来,对于人类读者来说,它可能看起来很奇怪和不合适。@Jiminion在某些情况下
-0.0
是有用的-即使它看起来不合适,例如四舍五入到接近的值。0但是想要显示0.0的哪一面,如In和财务四舍五入值,即仍然想要传达的最接近的百万,这是一个损失,尽管相对性很小,与年终利润-0.0百万一样。不建议将==与浮点数或双倍点数一起使用。一般来说,这是正确的,但在这种特殊情况下,您需要检查
d
是否正好是
0.0
-0.0
,这与
=
运算符无法区分。与
-DBL_EPSILON
相比是不正确的,因为你会将许多小的负非零值变成
0.0
。刚刚意识到这是一篇老文章!如果没有给出删除的答案,可能不会注意到。(我稍后会记下这句话)6.2.6.2只提到整数负零(不能出现在2的补码中)@chux:你能提供一个C标准的参考来支持你的说法吗?当结果是
-0.0
时,添加
0.0
?@chqrlie不需要实现"... 去除-当结果为-0.0时,添加0.0?”,但如果“定义
\uu STDC\u IEC\u 559\uuu
的实现应符合本附录中的规范”C11§F.1和“+”,−, *, 和/或运营商提供IEC 6
if (x == 0.0) x = 0.0;
d = -0.0
if (d < 0.0)
    do something...