1

When casting from a large uint64_t value to a double. The results are not as expected. Why is this, and is there a way to solve it. I'm using gcc 8.3.0

int main
{
   uint64_t var64 = 844421103279395000;

   printf("var64     = %llu\n", var64 );

   double varDouble = (double)var64;

   printf("varDouble = %lf\n", varDouble );

   return 0;
}

The output is as follows :

var64     = 844421103279395000
varDouble = 844421103279394940.000000
Engineer999
  • 3,683
  • 6
  • 33
  • 71
  • 1
    I'd suggest looking into how floating-point numbers are stored. You can always expect to lose precision when the number of bits of a number you want to store is greater than the number of bits in the mantissa of a floating-point number. According to Wikipedia, you can store 15.95 decimal digits in a 64-bit IEEE 754 floating-point number. – Thomas Jager May 07 '20 at 15:37
  • `double` has typically up to 53 bits precision, compared to 64. – Weather Vane May 07 '20 at 15:39
  • there are so many duplicates: [Are all integer values perfectly represented as doubles?](https://stackoverflow.com/q/43655668/995714), [biggest integer that can be stored in a double](https://stackoverflow.com/q/1848700/995714), [Can all 32 bit ints be exactly represented as a double?](https://stackoverflow.com/q/13269523/995714) – phuclv May 07 '20 at 15:46
  • Does this answer your question? [Which is the first integer that an IEEE 754 float is incapable of representing exactly?](https://stackoverflow.com/questions/3793838/which-is-the-first-integer-that-an-ieee-754-float-is-incapable-of-representing-e) – phuclv May 07 '20 at 15:46
  • Engineer999, "The results are not as expected." --> Exactly what did you expect? – chux - Reinstate Monica May 07 '20 at 17:47
  • All, note the `double` output is not the expected `844421103279394944.000000` either. We have more going on that usual `double` to `uint64_t` issue. Code, for some reasons ,is not printing the `double` as well as code could. Perhaps just a weak library. – chux - Reinstate Monica May 07 '20 at 17:55

1 Answers1

5

A double, assuming it uses IEE754 double-precision representation, can only hold 53 bits of precision. A uint64_t uses all 64 bits as value bits, meaning that there are some values that can be stored exactly in a uint64_t that cannot be stored exactly in a double.

In your example, 844421103279395000 has a hex representation of 0‭BB7 FC84 FDCF D0B8‬. The closest value with 53 bits of precision is 0‭BB7 FC84 FDCF D080 which is ‭844421103279394944‬ in decimal. This value is close to what is being displayed, with the difference probably due to how printf handles writing significant digits.

dbush
  • 205,898
  • 23
  • 218
  • 273