9

I have the following codes to cast a double into an int:

double dblValue = 7.30;
int intValue = (int)(dblValue*100);  //I want intValue to store exactly 730;
std::cout << intValue;

Output: 729

I know that the compiler is reading dblValue as 7.2999999 before casting it to int.

My question is: Is it possible to cast it as 730 by preventing the round down errors?

It would be best if your solution avoid using C++11 or other predefined functions. The only pre-processor directive I am using here is <iostream>.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
user3437460
  • 17,253
  • 15
  • 58
  • 106

4 Answers4

24

You cannot prevent rounding errors when converting a number that is not an integer (in the mathematical sense) to an integer, the only thing you can do is try to achieve proper rounding.

The easiest way to achieve a sensible (although not perfect) rounding is the following:

int intValue = (int)(dblValue < 0 ? dblValue - 0.5 : dblValue + 0.5);

And of course, since your question is tagged both c++ and casting I cannot resist replacing your c-style cast with a c++ style cast:

int intValue = static_cast<int>(dblValue < 0 ? dblValue - 0.5 : dblValue + 0.5);
danielschemmel
  • 10,885
  • 1
  • 36
  • 58
1

You can define your own integer truncation function that increases the value by the smallest possible amount, to make sure the rounded result is over the integer threshold.

#include <limits>

int int_cast(double x)
{
    return (int)(x * (1.0 + std::numeric_limits<double>::epsilon()));
}

If you don't want to depend on <limits> you can use DBL_EPSILON from <float.h> or substitute your own very small number. See also this question.

Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

C++11 added lround that helps to avoid precision loss on implicit double to long truncating cast:

int intValue = (int) lround(dblValue*100)

long to int cast won't loose precision too.

There is no iround(), unfortunately.

Update

I guess there is no iround() because any 32-bit integer will allways fit completely in 52 precision bits of 64-bit double. So there is no chance of precision loss on direct double to int truncation:

int intValue = (int) round(dblValue*100)
Vadzim
  • 24,954
  • 11
  • 143
  • 151
0

It's not any type of error, it's the way computer stores floating-point values. You can do something like this:

int intValue = (int)(dblValue*100 + 0.00001);
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • 1
    Actually, this isn't purely due to the way computers store floating-point values. You'd have the same problems converting a mathematical real to a mathematical integer. – James Kanze Apr 29 '14 at 20:23
  • 1
    not to mention this doesn't fix negative numbers or rounding up on the half – cppguy Apr 29 '14 at 20:46