Binary operations on doubles in C

2019-08-30 10:42发布

问题:

I'm working on a high speed computing problem for a large scale simulation. In order to speed up the process I wish to make a couple of optimizations, one of which is to compute the absolute value of a double in only a couple of cycles without jumps.

My idea was, that 64-Bit double values are represented with a 1-Bit sign Bit, an 11-Bit exponent and a 52-Bit Mantissa. So a double value XOR-ed with a mask: 10000000 00000000 00000000 00000000 would yield the desired result:

double abs(double x) {
    double mask = -0.0e0;
    return x^mask;
}

Now obviously there are few reason one would need binary operations on doubles, so naturally the compiler throws an error:

error: invalid operands to binary ^ (have ‘double’ and ‘double’)

I was wondering whether there was any way to make this work in a fast fashion, since I didn't wish to convert the whole thing into a char-array and back as was suggested elsewhere. That would sort of defeat the purpose of fast computing.

I'm thankful for all help...

回答1:

Variation on @Artur:
.. Use matching sized integer.
.. Initialize union with double. Not faster, but tighter.

#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;
}

Note: I'd stay with fabs() unless profiling showed other solutions faster.



回答2:

Have not checked but this should do the job:

double abs(double x) 
{
    long long tmp = *((long long*)&x);
    tmp &= ~(1LL << 63);
    return *((double*)&tmp);
}

Update:

Users commenting my solution were right about problems with above code. This should be better:

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


回答3:

double x;
int *p = (int *)&x;
*(p+1) ^= (1 << 31);


标签: c binary double