4

This is a small program that calculates the gaps of 'interval' size that are beetween two numbers 'from' 'to'. Then I calculate the 'size' (number of gaps) and store it in an int variable, and give me a smaller value sometimes.

Here is the code:

double from=0, to=1, interval=0.1;

cout << "WORKING WITH VARIABLES: " << endl;
double operation = (to-from)/interval +1;
cout << "Size: " << operation << endl;

int size = operation;

cout << "Size after storing: " << size << endl << endl;

cout << "WORKING WITHOUT VARIABLES: " << endl;
cout << "Size: " << (to-from)/interval +1 << endl;

size = (to-from)/interval +1;

cout << "Size after storing: " << size << endl << endl;

Problem seems to be in how it's stored interval. If interval=1 everything is good, but if is 0.1, as in the example it give me 10 instead 11 in the "Size after storing" of the second case.

I've found out that it works well with interval=0.25 (2^-2).

EDIT: I haven't found that it fails in the first case, always does in the second.

6
  • 1
    I think this is just due to representation of double objects. For example a cast to int from 0.999999 will be 0.0 but a cast to int from 1.000000001 will be 1.0. Commented Jul 18, 2014 at 11:40
  • What compiler are you using ? I get the right result with xcode (clang) and g++ Commented Jul 18, 2014 at 11:43
  • Did you try to debug and see in which place the number becomes wrong? Check what (to-from)/interval operation returns. Commented Jul 18, 2014 at 11:44
  • @IAmJohn I'm using MinGW32 g++ Commented Jul 18, 2014 at 11:46
  • @PiotrChojnacki The operation returns the rigth value, it's checked in the first case. Commented Jul 18, 2014 at 11:47

3 Answers 3

5

Floating point numbers are stored with a finite precision, and in binary. 0.25 is easy. That's just 1/4, so 0.01 binary. 0.1 is 1/10, which cannot be represented by a finite binary string. It's 1/16+1/32+ ...

So 1/10 is rounded down, and 10 * 1/10 is slightly less than 1.

As for the different results in the first and second case, that's probably because intermediate values are rounded to more digits than double has.

Sign up to request clarification or add additional context in comments.

2 Comments

Ok, I understand that. But why could it fail in the second case and not in the first?
@Jumer - Generate the assembly code and see the difference. Basically you cannot be guaranteed how (in)accurate the floating point will be, even if you are doing the same operation in another part of your program. See here: parashift.com/c++-faq/floating-point-arith2.html
5

You are suffering from the inaccuracies inherent in floating point arithmetic. What you probably get in the 0.1 case is 10.999.... instead of 11. Converting double to int truncates instead of rounding so you get 10. Add a small value before converting to int to combat this.

int size=operation+0.0000000001;

Comments

0

If you want to convert a double that is close to an integer (due to rounding errors, as explained by others) to an int, always round the value to the nearest integer, e.g. with round(), before converting the value to int, since double to int conversion truncates the value and will yield an incorrect result if the error is negative.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.