Sahee Sahee - 1 month ago 12
C Question

8 byte double as binary string to uint64_t

Im looking for way to convert 8 byte double to uint64_t. I cant use any standard library becouse of that there is only 4byte double in my solution.

This conversion should convert 10987789.5 to 10987789 as int.

Conversion that I use right now:

uint64_t binDoubleToUint64_t(char *bit){
uint8_t i, j;
uint64_t fraction;
for(i=0; i<64; i++)
bit[i]-='0';

uint16_t exponent = bit[1] ? 1 : 0;

j = 0;
for(i=9; i>0;i--)
exponent += bit[i+2] * int_pow(2, j++);

bit[11] = bit[1];
fraction = 0;
j=0;

for(i=0; i < exponent; i++){
fraction = fraction << 1;
if(bit[11+i])
fraction |= 1 << 1;
}
return fraction;
}


But this give me wrong answers.
While I try to convert double 10225203.0 (0x416380c660000000) it returns 10225202 (should 10225203)

Answer

Can you read the bit values straight in as a uint64_t. Then the code might look something like this:

uint64_t binDoubleToUint64_t (uint64_t in) {
  if (!(in & 0x4000000000000000) || in & 0x800000000000000000) {
    /* If the exponent isn't big enough to give a value greater than 1
     * or our number is negative return 0. 
     */
    return 0;
  }

  uint32_t exponent = ((in & 0x7FF0000000000000) >> 52) - 1023;

  // get the mantissa including the imagined bit.
  uint64_t mantissa = (in & 0xFFFFFFFFFFFFF) | 0x10000000000000;

  // Now we just need to work out how much to shift the mantissa by.
  uint32_t mantissaTopBit = 52;

  if (mantissaTopBit > exponent)
    return mantissa >> mantissaTopBit - exponent;
  else {
    if (exponent - mantissaTopBit > 12) {
       //You're in trouble as your double doesn't fit into an uint64_t
    }

    return mantissa << exponent - mantissaTopBit;
  }
}

This has been written from my memory of the floating point spec (I haven't checked all the values) so you may want to check the values given. It works for your examples, but you may want to check that I've put the right number of '0's in everywhere.

Comments