1

When I input 0.50 or other floats that can be divided by 0.25 I don´t get any error but when I input 0.10 or other float that can´t be divided by 0.25 the else if statement that I have written does not happen. Can anyone tell me why?

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

int main(void) {
    float change;
    do {
        change = get_float("Change owed: ");        
    } while (change < 0.009);
    int count = 0;
    int div = 0;
    while (change > 0.00) {
        if ((change / 0.25) >= 1.00) {
            div = round(change / 0.25);
            count += div;
            change = change - (div  *0.25);
        } else
        if ((change / 0.10) >= 1.00) {
            div = round(change / 0.10);
            count += div;
            change = change - (div * 0.10);
        } else
        if ((change / 0.05) >= 1.00) {
            div = round(change / 0.05);
            count += div;
            change = change - (div * 0.05);
        } else {
            div = round(change / 0.01);
            count += div;
            change = change - (div * 0.01);
        }
    }
    printf("%i\n", count);
}
S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
Manu
  • 11
  • 2
  • 1
    Step your program in the debugger and see what happens... – Paul Ogilvie Aug 13 '19 at 14:11
  • 4
    Does the assignment say you have to manipulate all your amounts as `float`? Usually for this sort of problem it's infinitely easier to use an `int`, but representing cents -- that is, $1.00 is represented as `100`. – Steve Summit Aug 13 '19 at 14:16
  • 5
    Also, see [**Why not use Double or Float to represent currency?**](https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency) – Andrew Henle Aug 13 '19 at 14:17
  • 3
    For your special values: `0.5` and `0.25` are perfect powers of 2 and can be represented without rounding. On the other hand `0.1` is not. – Gerhardh Aug 13 '19 at 14:22
  • Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Gerhardh Aug 13 '19 at 14:23
  • 1
    One problem in you algorithm is the use of round, you should use floor() instead, to round to the lower integer. – Chelmy88 Aug 13 '19 at 14:25
  • `printf("%.20f\n", 0.10)` → `0.10000000000000000555` – Armali Aug 13 '19 at 14:30
  • literals, like: `0.009`, `0.00`, `0.25`, etc are `doubles`, not `floats` To make them `floats`, append a `f` to the end of the literal. – user3629249 Aug 14 '19 at 15:40
  • Please read the MAN page for `round()` especially the paragraph: *These functions round x to the nearest integer, but round halfway cases away from zero (regardless of the current rounding direction, see fenv(3)), instead of to the nearest even integer like rint(3). For example, round(0.5) is 1.0, and round(-0.5) is -1.0.* And since the posted code is working with `float` values, you should be using: `roundf()` rather than `round()` – user3629249 Aug 14 '19 at 15:42
  • @Manu: you can accept the answer by clicking on the grey checkmark below its score. – chqrlie Aug 16 '19 at 17:44

1 Answers1

6

The internal representation of floating point numbers C is almost always the binary formats specified in the IEEE 754 binary representations, not a decimal form. As a consequence, some numbers with a simple representation in decimal notation such as 0.1 as not represented exactly in a float or even in a double variable. Multiplying this variable by 10 does not necessarily yield the value 1 exactly, but a very close floating point number different from 1. Comparing floating point numbers should be done with extreme care, allowing for the small differences coming from the propagation of the rounding method. In particular, you should avoid using float or double for currency values where the exact number of cents matters: use an integer holding the number of cents with a large enough size to handle the computed numbers. Regular 32-bit int would not suffice for numbers greater than 20 million USD expressed in cents.

Here is a modified version using long int for at least 32-bit size:

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

int main(void) {
    float change = get_float("Change owed: ");        
    long int cents = round(change * 100); // get an exact number of cents.
    long int count = cents / 25;  // number of quarters
    cents %= 25;
    count += cents / 10;     // number of dimes
    cents %= 10;
    count += cents / 5;      // number of nickels
    cents %= 5;
    count += cents;          // number of pennies
    printf("%ld coins\n", count);
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189