0

I have a class reading csv file containing numerical records with no more than two digits after the decimal point.

int ReadCellWithFloat(int cellNumber, int multiplier) throw (FSByFieldException)
{
    GoToCell( cellNumber );
    float number;
    FileStream >> number;
std::cout << "what we've got: " << number;
    if ( !FileStream.good() )
    {
        throw BuildException( FSByFieldException::NOT_FLOAT );
    }
    while ( multiplier-- )
    {
        number *= 10;
    }
std::cout << ' ' << number << ' ' << (int) number << std::endl;
    PassCell(); // here meaning pass comma separator
    return (int) number;
}

For a cell containing float "8.49" the output yields:

what we've got: 8.49 849 848

Why 849 turns to 848 on casting to integer and how to fix it?

yauser
  • 707
  • 2
  • 8
  • 19

3 Answers3

2

849 turns to 848 because a pure cast simply truncates the value. So (int) 4.8 == 4. You might think that 8.49 * 10 * 10 is 849, but it's not necessarily true :) it is just as close to 849 as the architecture can represent, which might internally be something like 848.999999... which becomes 848 once truncated.

To fix it, you can use (int) round(number), and you might also be interested in taking a look at the ceil() and floor() functions, and general information regarding floating point precision issues, to avoid having trouble with number comparisons and whatnot.

i Code 4 Food
  • 2,144
  • 1
  • 15
  • 21
0

The number 8.49 can not be exactly represented, so when you multiply it by 10 twice you end up with something more like 848.99999, when I try this out:

number = 8.49 ;
number *= 10 ;
number *= 10 ;

std::cout << std::fixed << number << std::endl ;

I get 848.999939, when you cast to integer it is truncating and so you end up with 848. Using roundf will give you the result you want:

std::cout << std::fixed << roundf(number) << std::endl ;

in C++11 you would just use round.

Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
0

This is because how floats are stored in binary space. This link will show you that a value of 8.49 is best represented as a float of 8.4899997.

Therefore, when you cast the float as an int, it will resolve the actual value of the float rather than the rounded value.

There are a few ways you can get around this: 1) Use double precision (which will abate this problem, not not eliminate it) 2) Round up the number 848.99 using the math libraries. 3) Add 0.5 to all numbers before casting as int.

John Phu Nguyen
  • 319
  • 1
  • 9
  • I'm not familiar with any implementation of casting that rounds the float; it's always trunc, as far as I know. – Mike C May 17 '13 at 01:25
  • You're correct. I agree that it always truncates. Sorry if any part of my answer was confusing. My solution to this problem would be to add 0.5 to the number before casting as int such as (int)(849.99997 + 0.5). That way you can avoid including the math libraries for this simple task. – John Phu Nguyen May 17 '13 at 01:33