我正在为大规模模拟研究高速计算问题。为了加快这个过程,我希望进行一些优化,其中一个是在没有跳跃的情况下仅在几个周期内计算double的绝对值。
我的想法是,64位双值用1位符号位,11位指数和52位尾数表示。所以带掩码的双值XOR-ed: 10000000 00000000 00000000 00000000将产生所需的结果:
double abs(double x) {
double mask = -0.0e0;
return x^mask;
}
现在显然没有理由需要对双精度进行二进制运算,因此编译器自然会抛出错误:
error: invalid operands to binary ^ (have ‘double’ and ‘double’)
我想知道是否有任何方法可以快速完成这项工作,因为我不希望将整个事物转换为char-array并返回其他地方所建议的。这有点会破坏快速计算的目的。
我很感谢所有人的帮助......
答案 0 :(得分:2)
@Artur的变化:
..使用匹配大小的整数
..用double初始化union。不是更快,但更紧。
#include <stdint.h>
double Abs_double(double d) {
union {
double d;
uint64_t u64;
} u = {d};
u.u64 &= ~( (uint64_t) 1 << 63);
return u.d;
}
注意:除非分析更快地显示其他解决方案,否则我将继续使用fabs()
。
答案 1 :(得分:1)
没有检查,但这应该做的工作:
double abs(double x)
{
long long tmp = *((long long*)&x);
tmp &= ~(1LL << 63);
return *((double*)&tmp);
}
<强>更新强>
评论我的解决方案的用户对上述代码的问题是正确的。这应该更好:
double my_abs(double x)
{
union my64bits
{
unsigned long long a;
double b;
};
union my64bits tmp;
tmp.b = x;
tmp.a &= ~(1uLL<<63);
return tmp.b;
}
答案 2 :(得分:-3)
double x;
int *p = (int *)&x;
*(p+1) ^= (1 << 31);