C中双打的二进制运算

时间:2013-12-08 19:43:10

标签: c binary double

我正在为大规模模拟研究高速计算问题。为了加快这个过程,我希望进行一些优化,其中一个是在没有跳跃的情况下仅在几个周期内计算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并返回其他地方所建议的。这有点会破坏快速计算的目的。

我很感谢所有人的帮助......

3 个答案:

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