在C中,当±0.0支持-0.0或+0.0分配给a时double通常不会产生算术差异.尽管它们具有不同的位模式,但它们在算术上比较相同.
double zp = +0.0;
double zn = -0.0;
printf("0 == memcmp %d\n", 0 == memcmp(&zn, &zp, sizeof zp));// --> 0 == memcmp 0
printf("== %d\n", zn == zp); // --> == 1
Run Code Online (Sandbox Code Playgroud)
受到@Pascal Cuoq评论的启发,我正在寻找标准C中的一些功能,这些功能提供了算术上不同的结果.
注意:许多功能,如sin(),返回+0.0从f(+0.0)和-0.0从f(-0.0).但这些并不能提供不同的算术结果.这两个结果也不应该同时存在NaN.
在我们的代码库中,我们有很多操作,如j*ω*X,其中j是虚数单位,ω是实数,X是复数.实际上很多循环看起来像:
#include <complex>
#include <vector>
void mult_jomega(std::vector<std::complex<double> > &vec, double omega){
std::complex<double> jomega(0.0, omega);
for (auto &x : vec){
x*=jomega;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我们利用了真实部分jomega为零的事实并将乘法写为:
void mult_jomega_smart(cvector &vec, double omega){
for (auto &x : vec){
x={-omega*x.imag(), omega*x.real()};
}
}
Run Code Online (Sandbox Code Playgroud)
一开始,我对这种"聪明"的转变不屑一顾,因为
然而,正如一些表现回归所显示的那样,第三个论点并不成立.当比较这两种功能(见下文列表),智能版采用一贯优于-O2以及具有-O3:
size orig(musec) smart(musec) speedup
10 0.039928 0.0117551 3.39665
100 0.328564 0.0861379 3.81439
500 1.62269 0.417475 3.8869
1000 3.33012 0.760515 4.37877
2000 6.46696 1.56048 4.14422
10000 32.2827 9.2361 3.49528
100000 326.828 115.158 2.8381 …Run Code Online (Sandbox Code Playgroud)