-1

I can't understand why the code below doesn't work properly with the value 4.2. I learnt using a debugger that 4.2 isn't actually the number four point two; rather as a floating point value 4.2 becomes 4.19999981

To make up for this, I just added change = change + 0.00001; there on line 18.

Why do I have to do that? Why is this the way floating point integers work?

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

float change;
int coinTotal;

int main(void)
{
do {

// Prompting the user to give the change amount
    printf("Enter change: ");

// Getting a float from the user
    change = get_float();
    }
    while (change < 0);
    change = change + 0.00001;

// Subtracting quarters from the change given
    for (int i = 0; change >= 0.25; i++)
    {
        change = change - 0.25;
        coinTotal++;
    }

// Subtracting nickels from the remaining change
    for(int i = 0; change >= 0.1; i++)
    {
        change = change - 0.1;
        coinTotal++;
    }

// Subtracting dimes from the remaining change
    for(int i = 0; change >= 0.05; i++)
    {
        change = change - 0.05;
        coinTotal++;
    }

// Subtracting pennies from the remaining change
    for(int i = 0; change >= 0.01; i++)
    {
        change = change - 0.01;
        coinTotal++;
    }

// Printing total coins used
    printf("%i\n", coinTotal);
}
akshayk07
  • 2,092
  • 1
  • 20
  • 32
withwavy
  • 33
  • 5
  • 2
    Please see [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken). Remember that a 32-bit `float` has fewer than 2^32 discrete values that span a range of about 10^39 so inaccuracy is inevitable. – Weather Vane Jul 22 '17 at 01:04
  • 1
    Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Daniel Pryden Jul 22 '17 at 04:12
  • I would recommend to multiply the input value by 100 and the work directly with integers. With that said, you algorithm is incorrect, you implemented the iterative version, the fastest, but not the optimal. Using a greedy algorithm will ensure you give the least amount of coins: Supose you have the coins 11, 5 and 1 and you have to give 15. Your algorithm would return 5 (11+1+1+1+1), but the correct answer would be 3 (5+5+5). – ichramm Jul 22 '17 at 04:25

3 Answers3

1

As you have discovered. It's impossible to represent rational numbers as floating-point values on computers, due to the fact that the machine is storing it in a somewhat fixed sized ammount of bits.

The most common standard is IEEE 754 Check here

Most commonly you will work with floats that are in single precision (32 bits in total). The number is represented as 1 bit for sign, 8 bits for exponent , 23 bits for mantissa.
The representation is as follows x=S*M*B^E where:
S - sign (-1 or 1)
M - mantissa (a normalized fraction)
B - Base (here as 2)
E - exponent ( 8bits -> -128,127 or 0,255 depending on definition in standard)

This fraction is (M) causing the problems with accurate representation of values. You need to represent a certain aproximation while being given a limited ammount of bits (You can only accurately represent values that can be combined by summing 1/2, 1/4, 1/8... ) Commonly 32 bits allows you for precision for around 6 places in fraction.

You can use 64 bit (double) for a greater range and slightly better precision.

johnyyonehand
  • 52
  • 1
  • 6
  • 3
    “It's impossible to represent exact floating-point values on computers” No, floating-point values are represented exactly. It the rational numbers that aren't floating-point values that are not represented exactly. – Pascal Cuoq Jul 22 '17 at 11:24
1

Typically float can represent about 232 different values exactly. With float, 4.2 is not one of them. Instead the value is about 4.19999981 as OP has reported.

Working with fractional money is tricky. Rarely is float an acceptable type for money. This details some alternatives like base-10 FP, double, integers and custom types.


If code stays with some FP type, change >= 0.1, and other compares, need to alter to change >= (0.01 - 0.005) or the like. The compare needs to be tolerant of values just less than or greater than a multiple of 0.01.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

Make every number in your program 100 times bigger, use the math.h roundf function, and divide the result by 100 when you are about to print the value to the screen.

Cpp plus 1
  • 990
  • 8
  • 25