Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# int stored in double "==" precision problem

Here is the simplified code:

int i = 1;
double a = i;
double b = i;

Is it guarantied that a == b is true?

like image 543
levanovd Avatar asked Nov 27 '10 08:11

levanovd


2 Answers

Yes. 32-bit integers can be represented exactly as 64-bit floating point numbers.

like image 173
Ian Henry Avatar answered Oct 12 '22 22:10

Ian Henry


Is it guarantied that a == b is true?

Yes. This is because you perform the same conversion twice and given its deterministic behavior you will end up with the same values regardless of the rounding problems.

We can generalize your question though, to:

Can we perform arithmetic operations on 32-bit integer values encoded in double type without precision loose?

The answer for such question is yes as well.

A short justification is that operations on mantissa bits (see http://en.wikipedia.org/wiki/Significand) are precise if it is only possible and in case of 32-bit integer values it is possible.

Longer story comes here. As long as your integer value fits in 52 bits of a fraction part called mantissa (see http://en.wikipedia.org/wiki/Double_precision) all calculations on integer values using double will behave completely OK.

This is because your number (say 173 which is 0000010101101b binary) will be represented as 1.010110100000b*2^7, which is accurate.

All operations on mantissa are straight forward as long as they fit in mantissa. Rounding on integers occurs when result of a particular operation do not fit in mantissa - eg. you would multiply 40 bits of mantissa by 40 bits of mantissa. Rounding on floating point operations additionally occur when exponents are much different. In this case even a simple addition operation can loose precision because matissas are shifted.

Back to integers encoded in double - even division operation is precise, as long as the result is integer value. So 4.0/2.0 == 8.0/4.0 is also guaranteed to be true.

The problem begins when your number is not integer. But even in this case numbers are guaranteed to be represented precisely if they are a form of x/2^y and x fits in 52 bits (eg. 3/4 5/8 345/1024). Operations on such numbers are also precise given y can be equal for both operands, so even:

123456789/1024/1024/1024/1024 == 
(23456789/1024/1024/1024/1024 +
100000000/1024/1024/1024/1024)

is guaranteed to be true.

Interesting fact is that you can perform operation on 54 bit signed integers safely. This is because you have additional bit at the beginning whose meaning is encoded by the exponent and one additional bit for a sign. Now -2^53 which would be MIN_INT in case of 54 bit signed integer does not fit the mantissa, but exponent will do the job here with mantissa full of zeros.

like image 36
agsamek Avatar answered Oct 12 '22 22:10

agsamek