+0.0 和 -0.0 上的哪些运算和函数给出不同的算术结果? [英] What operations and functions on +0.0 and -0.0 give different arithmetic results?
问题描述
在 C 中,当支持 ±0.0
时,通常将 -0.0
或 +0.0
分配给 double
没有算术的区别.虽然它们有不同的位模式,但它们在算术上是相等的.
In C, when ±0.0
is supported, -0.0
or +0.0
assigned to a double
typically makes no arithmetic difference. Although they have different bit patterns, they arithmetically compare as equal.
double zp = +0.0;
double zn = -0.0;
printf("0 == memcmp %d
", 0 == memcmp(&zn, &zp, sizeof zp));// --> 0 == memcmp 0
printf("== %d
", zn == zp); // --> == 1
灵感来自 @Pascal Cuoq 评论,我正在寻找标准 C 中的其他几个函数提供了算术上不同的结果.
Inspire by a @Pascal Cuoq comment, I am looking for a few more functions in standard C that provide arithmetically different results.
注意:许多函数,如 sin()
,从 f(+0.0)
和 -0.0<返回
+0.0
/code> 来自 f(-0.0)
.但是这些并没有提供不同的算术结果.两个结果也不应该都是 NaN
.
Note: Many functions, like sin()
, return +0.0
from f(+0.0)
and -0.0
from f(-0.0)
. But these do not provide different arithmetic results. Also the 2 results should not both be NaN
.
推荐答案
f(+0.0)
和 f(-0.0)
.
不同的舍入模式或其他浮点实现可能会产生不同的结果.
Different rounding modes or other floating point implementations may give different results.
#include <math.h>
double inverse(double x) { return 1/x; }
double atan2m1(double y) { return atan2(y, -1.0); }
double sprintf_d(double x) {
char buf[20];
// sprintf(buf, "%+f", x); Changed to e
sprintf(buf, "%+e", x);
return buf[0]; // returns `+` or `-`
}
double copysign_1(double x) { return copysign(1.0, x); }
double signbit_d(double x) {
int sign = signbit(x); // my compile returns 0 or INT_MIN
return sign;
}
double pow_m1(double x) { return pow(x, -1.0); }
void zero_test(const char *name, double (*f)(double)) {
double fzp = (f)(+0.0);
double fzn = (f)(-0.0);
int differ = fzp != fzn;
if (fzp != fzp && fzn != fzn) differ = 0; // if both NAN
printf("%-15s f(+0):%-+15e %s f(-0):%-+15e
",
name, fzp, differ ? "!=" : "==", fzn);
}
void zero_tests(void) {
zero_test("1/x", inverse);
zero_test("atan2(x,-1)", atan2m1);
zero_test("printf("%+e")", sprintf_d);
zero_test("copysign(x,1)", copysign_1);
zero_test("signbit()", signbit_d);
zero_test("pow(x,-odd)", pow_m1);; // @Pascal Cuoq
zero_test("tgamma(x)", tgamma); // @vinc17 @Pascal Cuoq
}
<小时>
Output:
1/x f(+0):+inf != f(-0):-inf
atan2(x,-1) f(+0):+3.141593e+00 != f(-0):-3.141593e+00
printf("%+e") f(+0):+4.300000e+01 != f(-0):+4.500000e+01
copysign(x,1) f(+0):+1.000000e+00 != f(-0):-1.000000e+00
signbit() f(+0):+0.000000e+00 != f(-0):-2.147484e+09
pow(x,-odd) f(+0):+inf != f(-0):-inf
tgamma(x) f(+0):+inf != f(-0):+inf
<小时>
注意事项:tgamma(x)
在我的 gcc 4.8.2 机器上出现了 ==
,但是 正确 !=
其他人.
Notes:
tgamma(x)
came up ==
on my gcc 4.8.2 machine, but correctly !=
on others.
rsqrt()
,又名 1/sqrt()
可能是未来的 C 标准函数.可能/可能不工作.
rsqrt()
, AKA 1/sqrt()
is a maybe future C standard function. May/may not also work.
双零 = +0.0;memcpy(&zero, &x, sizeof x)
可以显示 x
是与 +0.0
不同的位模式,但 x
仍然可以是 +0.0
.我认为某些 FP 格式有许多位模式,即 +0.0
和 -0.0
.待定.
double zero = +0.0; memcpy(&zero, &x, sizeof x)
can show x
is a different bit pattern than +0.0
but x
could still be a +0.0
. I think some FP formats have many bit patterns that are +0.0
and -0.0
. TBD.
这是由 https://stackoverflow.com/help/self-answer 提供的自我回答.
This is a self-answer as provided by https://stackoverflow.com/help/self-answer.
这篇关于+0.0 和 -0.0 上的哪些运算和函数给出不同的算术结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!