0

I know double has some precision issues and it can truncate values during conversion to integer.

In my case I am assigning a double 690000000000123455 and it gets changed to 690000000000123392 during assignment.

Why is the number being changed so much drastically? After all there's no fractional part assigned with it. It doesn't seems like a precision issues as value doesn't change by 1 but 63.

user4581301
  • 33,082
  • 7
  • 33
  • 54
Daman
  • 27
  • 2

4 Answers4

4

Presumably you store 690000000000123455 as a 64 bit integer and assign this to a double.

double d = 690000000000123455;

The closest representable double precision value to 690000000000123455 can be checked here: http://pages.cs.wisc.edu/~rkennedy/exact-float?number=690000000000123455 and is seen to be 690000000000123392.

In other words, everything is as to be expected. Your number cannot be represented exactly as a double precision value and so the closest representable value is chosen.

For more discussion of floating point data types see: Is floating point math broken?

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

IEEE-754 double precision floats have about 53 bits of precision which equates to about 16 decimal digits (give or take). You'll notice that's about where your two numbers start to diverge.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

double storage size is 8 byte. It's value ranges from 2.3E-308 to 1.7E+308. It's precision is upto 15 decimal places. But your number contains 18 digits. That's the reason.

You could use long double as it has precision upto 19 decimal places.

Shahid
  • 2,288
  • 1
  • 14
  • 24
  • @DavidHeffernan well, in MSVC and some windows compilers yes... is there any other? – M.M Aug 26 '16 at 05:13
  • @M.M It's the platform that matters more than the compiler. x87 has the 80 bit extended type which maps to long double typically. x64 offers sse unit for floating point with no type larger than 64 bit. I believe that ARM is the same. On these platforms long double is the same as double, typically. – David Heffernan Aug 26 '16 at 05:21
  • @DavidHeffernan `sizeof(1.0L)` gives `16` in x86_64 gcc for windows – M.M Aug 26 '16 at 05:25
  • @M.M That's probably the compiler deciding to use the 80 bit type on the x87 unit. http://stackoverflow.com/questions/15176290/what-is-long-double-on-x86-64 Expect performance to be somewhat lame. And do understand that 6 of the 16 bytes are padding. So I guess the compiler matters too! – David Heffernan Aug 26 '16 at 05:32
0

The other answers are already pretty complete, but I want to suggest a website I find very helpful in understanding how float point number works: IEEE 754 Converter (only 32-bit float here, but the interaction is still very good).

As we can see, 690000000000123455 is between 2^59 and 2^60, and the highest precision of the Mantissa is 2^-52 for double precision, which means that the precision step for the given number is 2^7=128. The error 63 you provided, is actually within range.

As a side suggestion, it is better to use long for storing big integers, as it will hold the precision and does not overflow (in your case).

lnyng
  • 925
  • 6
  • 18