-1

I am trying to figure out why i get two different outputs for seemingly similar loops. I think it has something to do with looping with doubles versus ints, but I am not sure.

This code outputs 4:

int num = 10;
int cost;
int counter = 0;

for (cost = 1; cost <= num; cost += 1){
    counter += 1;
    num -= cost;
}

cout << counter << endl;

This is the output for this section:

Current Cost: 1
Remaining: 9
Current Cost: 2
Remaining: 7
Current Cost: 3
Remaining: 4
Current Cost: 4
Remaining: 0
4 candies; 0 left over

This code outputs 3:

double num = 1.0;
double cost; 
int counter = 0;

for(cost = 0.1; cost <= num; cost += .1) {
    counter +=1;
    num -= cost;
}

cout << counter << endl;

Edit:

This is the output for this code when I tried debugging it:

    Current Cost: 0.1
    Remaining: 0.9
    Current Cost: 0.2
    Remaining: 0.7
    Current Cost: 0.3
    Remaining: 0.4        
    3 candies; 0.400000 left over

Why is there a difference between the two?

Biggytiny
  • 519
  • 10
  • 29
  • 3
    Follow it in your debugger, or put output statements inside the loop so you can see what the value of each variable is at any time – M.M Apr 18 '17 at 01:07
  • [Take care. `double` can be fuzzy.](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – user4581301 Apr 18 '17 at 01:12
  • @M.M I did that already, and still could not deduce the issue, which is why I came here to seek the help of someone who knows better than I. – Biggytiny Apr 18 '17 at 01:14
  • At some stage of your debugging you would find the point where the actual behaviour differs from your expectations. Then investigate that point specifically. – M.M Apr 18 '17 at 01:16
  • @M.M take a look at the edit, do you have any explanation as to why it exits the loop? – Biggytiny Apr 18 '17 at 01:26
  • @Biggytinyq because you didn't print enough digits in your debugger and/or code. Call [`cout.precision(20);`](http://stackoverflow.com/q/554063/995714) and you'll see the problem right away. Demo http://ideone.com/CJuNQZ – phuclv Apr 18 '17 at 01:57
  • @Biggytiny [Using floating point variables as loop counters](https://www.securecoding.cert.org/confluence/display/c/FLP30-C.+Do+not+use+floating-point+variables+as+loop+counters) – PaulMcKenzie Apr 18 '17 at 02:24

1 Answers1

2

I probably should not be doing this, but I debugged your code and the double loop fails in the 4th iteration:

Both cost and num take the values of 0.4, but:

cost <= num;

evaluates to false; This is due to the nature of doubles being stored with so much precision. I would suggest avoiding ==, >= and <= statements when dealing with doubles. A solution would be to convert your loop to:

for(cost = 0.1; cost < num+0.001; cost += .1) {
    counter +=1;
    num -= cost;
}

therefore solving the precision issue, but I would recommend against it as it could lead to problems in a more complex environment.

Kostas
  • 4,061
  • 1
  • 14
  • 32
  • Thank you very much this is the answer I was looking for, not people telling me to debug the code which I did before coming here. Much appreciated. – Biggytiny Apr 18 '17 at 01:30
  • both `cost` and `num` **can't** take the value 0.4 (unless you're using a strange compiler that uses decimal float), because there's no such value in binary floating-point. They can just take the closest value. Even then [your suggested way is not a good way for floating-point comparison](http://stackoverflow.com/q/17333/995714) http://floating-point-gui.de/errors/comparison/ – phuclv Apr 18 '17 at 01:55