# Float to int not truncating correctly

• 10-13-2012
hi_friends
Float to int not truncating correctly
Hello,

Code:

```#include <stdio.h> main() {     int xs[] = {2,4,5,80,80,80,160,320,640,640};     int i;     double sum = 0;         for(i = 0; i < 10; i++) {         sum += (1.0/xs[i]);     }         i = sum;         printf("sum = %f i = %d\n", sum, i); // i should be 1 ...         if(i == 1) printf("Everyone is happy 1.\n");         sum = 1.000000;     i = sum;         printf("sum = %f i = %d\n", sum, i); // now i = 1. why?         if(i == 1) printf("Everyone is happy 2.\n"); }```
A workaround is: i = sum+0.00001;
But I was curious why it is happening. Anyone could explain, please?

gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)
• 10-13-2012
oogabooga
You are asking too much from the floating point representation. The only fractional values that can be represented with complete accuracy are those that are (negative) powers of two or the sum of such powers. Anything else must be approximated.
E.g.,
0.5 decimal in binary is 0.1
0.2 decimal in binary is 0.001100110011...

So 0.5 can be represented with complete accuracy, but 0.2 cannot (similar to how 1/3 cannot be represented with complete accuracy in decimal).

Thus the truncation is working perfectly since the approximated value is less than 1. Your workaround is the proper way to go, although you could probably just add DBL_EPSILON (from float.h).

For all the info you'd ever want, see What Every Computer Scientist Should Know About Floating-Point Arithmetic
• 10-13-2012
JohnGraham
Quote:

Originally Posted by hi_friends
Code:

```    sum = 1.000000;     i = sum;         printf("sum = %f i = %d\n", sum, i); // now i = 1. why?```

Is this code out of place or something? Of course i will be 1 - you've just set it to 1...

Also, if you're having trouble rounding floating-point numbers, consider using round() from math.h.
• 10-13-2012
hi_friends
Quote:

Originally Posted by JohnGraham
Is this code out of place or something? Of course i will be 1 - you've just set it to 1...

Well, so I think you didn't run the code. I assign sum to i twice, and the first time sum also has the value 1.000000 (at least this is what is printed), but the value of i is ZERO.

Quote:

Originally Posted by JohnGraham
Also, if you're having trouble rounding floating-point numbers, consider using round() from math.h.

Thank you, but I don't want to round. I was just expecting a "proper" behavior for truncating.
• 10-13-2012
Nominal Animal
Quote:

Originally Posted by hi_friends
Well, so I think you didn't run the code. I assign sum to i twice, and the first time sum also has the value 1.000000 (at least this is what is printed), but the value of i is ZERO.

Try using %.24f in the printf statement to see the actual value. You'll find that it's value is 0.999999999999999888977698 and not 1.

(By the actual value, I mean that since IEEE-754 double-precision floating point has about 17 digits of precision, using 24 or so should give you a value which, when converted back to floating-point, has the exact same bit representation.)
• 10-13-2012
grumpy
Quote:

Originally Posted by hi_friends
Thank you, but I don't want to round. I was just expecting a "proper" behavior for truncating.

The defined "proper" behaviour in C is rounding towards zero. So a floating point value which is very close to 1, but slightly less than 1, will become zero when converted to an int.
• 10-14-2012
hi_friends
Quote:

Originally Posted by Nominal Animal
Try using %.24f in the printf statement to see the actual value. You'll find that it's value is 0.999999999999999888977698 and not 1.

(By the actual value, I mean that since IEEE-754 double-precision floating point has about 17 digits of precision, using 24 or so should give you a value which, when converted back to floating-point, has the exact same bit representation.)

Very nice. Thank you.
Sorry folks, the value of sum after the loop was not 1.
Is there a way to mark the thread as solved?
Thanks everyone.
• 10-14-2012
Click_here
I usually add 0.5 to a floating number before converting it to an int as a work around.