Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this double to int conversion not work?

I've been thoroughly searching for a proper explanation of why this is happening, but still don't really understand, so I apologize if this is a repost.

#include <iostream>
int main()
{
    double x = 4.10;
    double j = x * 100;

    int k = (int) j;

    std::cout << k;
 }

 Output: 409

I can't seem to replicate this behavior with any other number. That is, replace 4.10 with any other number in that form and the output is correct.

There must be some sort of low level conversion stuff I'm not understanding.

Thanks!

like image 618
Koma Avatar asked May 02 '11 01:05

Koma


People also ask

Is conversion from double to int possible?

round() method converts the double to an integer by rounding off the number to the nearest integer. For example – 10.6 will be converted to 11 using Math. round() method and 1ill be converted to 10 using typecasting or Double.

How do I convert a double to an int in C++?

The syntax for typecasting is like the syntax for a function call. For example: double pi = 3.14159; int x = int (pi); The int function returns an integer, so x gets the value 3.


2 Answers

4.1 cannot be exactly represented by a double, it gets approximated by something ever so slightly smaller:

double x = 4.10;
printf("%.16f\n", x);  // Displays 4.0999999999999996

So j will be something ever so slightly smaller than 410 (i.e. 409.99...). Casting to int discards the fractional part, so you get 409.

(If you want another number that exhibits similar behaviour, you could try 8.2, or 16.4, or 32.8... see the pattern?)

Obligatory link: What Every Computer Scientist Should Know About Floating-Point Arithmetic.

like image 130
Oliver Charlesworth Avatar answered Nov 15 '22 19:11

Oliver Charlesworth


The fix

int k = (int)(j+(j<0?-0.5:0.5));

The logic

You're experiencing a problem with number bases.

Although on-screen, 4.10 is a decimal, after compilation, it gets expressed as a binary floating point number, and .10 doesn't convert exactly into binary, and you end up with 4.099999....

Casting 409.999... to int just drops the digits. If you add 0.5 before casting to int, it effectively rounds to the nearest number, or 410 (409.49 would go to 409.99, cast to 409)

like image 31
Phil Lello Avatar answered Nov 15 '22 21:11

Phil Lello