user2511929 user2511929 - 4 months ago 28
C Question

C while-loop not stopping

#include <cs50.h>
#include <stdio.h>

int main(void) {

printf("Enter your change: ");
int pennies = 0, nickels = 0, dimes = 0, quarters = 0;
float change = GetFloat();

while (change > 0) {
if (change >= 0.25) {
quarters++;
change -= 0.25;
}
else if (change >= 0.10) {
dimes++;
change -= 0.10;
}
else if (change >= 0.05) {
nickels++;
change -= 0.05;
}
else if (change >=0.01) {
pennies++;
change -= 0.01;
}
// force break
else {
printf("%1.2f - Num. of change left\n", change);
break;
}
}
printf("Quarters: %d\n", quarters);
printf("Dimes: %d\n", dimes);
printf("Nickels: %d\n", nickels);
printf("Pennies: %d\n", pennies);
return 0;
}


Hello, I'm currently new to C and I'm taking Harvard's CS50 class online. The "change" variable seems to go down to 0.00 without stopping the while-loop. This forced me to type in "break" at the end. What is wrong with my code?

This is from problem set 1 by the way.

Answer

There are problems with how floating point numbers are represented in a computer memory. If in short: not all numbers can be stored precisely. Please read this page for more details: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

You can use this service to check the representations of floats in a computer: http://www.binaryconvert.com/result_float.html

Regarding your case, let's assume you have entered 0.4. That means it should be divided into 0.25 + 0.1 + 0.05. And change is supposed to be zero, but:

0.40 == 0.4000000059604644775390625000,
 minus
0.25 == 0.2500000000000000000000000000 (exact),
 minus
0.10 == 0.1000000014901161193847656250,
 minus
0.05 == 0.0500000007450580596923828125
 is
0.00 == 0.0000000037252902984619140625

As you can see, the final result is slightly above zero, what prevents your loop from ending.

Generally, if you need to count money, you should use int instead to count "cents". Or custom types. Or long arithmetic. Or whatever, but not floating points, because money in most countries needs only two positions after a point, thus this point needs not to be floating.