This informal discussion sprung from Suzi's post describing a problem with this program [code reproduced with permission]:
#include <stdio.h> char line[50]; float amount; /* the amount of $ as entered by the user */ int total; /* amount * 100, converted to an interger */ int dollars; /* # of dollars needed to make change */ int quart; /* # of quarters needed */ int dime; /* # of dimes needed, etc. */ int nick; int penn; int main() { while (1) { /* inputting dollar amount */ printf("Enter the amount of money to make change for: $"); fgets(line, sizeof(line), stdin); if (sscanf(line, "%f", &amount) <= 0) break; while (amount <= 0) { printf("Please enter an amount greater than 0: $"); fgets(line, sizeof(line), stdin); if (sscanf(line, "%f", &amount) <= 0) break; } total = amount * 100; /* determining how many of each coin is needed */ dollars = total / 100; total %= 100; quart = total / 25; total %= 25; dime = total / 10; total %= 10; nick = total / 5; penn = total % 5; /* printing the change needed. Program should only print a type of * coin if it is needed to make change (i.e. it should not print * "0 quarters". */ printf("To make change for $%.2f, you need:\n", amount); if (dollars > 1) printf("%d dollars\n", dollars); if (dollars == 1) printf("%d dollar\n", dollars); if (quart > 1) printf("%d quarters\n", quart); if (quart == 1) printf("%d quarter\n", quart); if (dime > 1) printf("%d dimes\n", dime); if (dime == 1) printf("%d dime\n", dime); if (nick == 1) printf("%d nickel\n", nick); if (penn > 1) printf("%d pennies\n", penn); if (penn == 1) printf("%d penny\n", penn); } return (0); }
It didn't behave correctly when there was change of a single penny (1 cent, or 0.01 dollars) involved.
Mary made a long post in response which eventually identified a floating point error, a quite subtle bug.
Online references
Solutions
Different solutions to Suzi's problem were suggested:
- Suzi's solution [manually rounding to correct for floating point errors]
- Christopher's solution [using round or lround]
- Conor's solution [correcting manual rounds for negative numbers] and his correction
- Lorne's solution [cutting floating point numbers out of the equation altogether]