0

This is a simple question and I searched the forums, but couldn't find an answer (I found one about Log but I don't think there is a rounding error here).

I wrote a program to determine the value of a fine for a range of expired products, but when the ratio is exact, the program will return the next fine category, ignoring the = sign in the conditional.

The program must return the following fines:

  • 0 if no product is expired.
  • 100 if up to 10% of products are expired.
  • 10000 if more than 10% of products and up to 30% are expired.
  • 100000 if more than 30% of products are expired.

This is the code I wrote:

#include <stdio.h>
int calculate_fine(int ncheckedproducts, int nexpiredproducts)
{
    int fine;
    float ratio;
    ratio=(float)nexpiredproducts/ncheckedproducts;

    if(nexpiredproducts==0)
        fine=0;
    else

        if(ratio<=0.1)
            fine=100;
        else

            if(ratio<=0.3)
                fine=10000;
            else
                fine=100000;

    return fine;
}

int main(void)
{
    int ncheckedproducts, nexpiredproducts, fine;
    printf("Type number of checked and expired products\n");
    scanf("%d %d", &ncheckedproducts, &nexpiredproducts);
    fine=calculate_fine(ncheckedproducts, nexpiredproducts);
    printf("The fine is: %d\n", fine);
    return 0;
}

But for values of 100 and 10, and 100 and 30, exactly 10% and 30% of expired products respectively, the program will return the wrong fine.

The teacher failed to explain me why, and corrected me to the following function:

int calculate_fine(int ncheckedproducts, int nexpiredproducts)
{
    int fine;

    if(nexpiredproducts==0)
        fine=0;
    else

        if(nexpiredproducts<=0.1*ncheckedproducts)
            fine=100;
        else

            if(nexpiredproducts<=0.3*ncheckedproducts)
                fine=10000;
            else
                fine=100000;

    return fine;
}

However, I wish to know why the first 10% ratio is greater than 0.1, and why I cannot use this approach.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140

2 Answers2

1

This most probably is a rounding issue, but a different than you might think: Many finite decimal fractions do not have a finite binary fraction representation. Thus, some rounding the the closest number representable as a floating point number of the given type happens.

das-g
  • 9,718
  • 4
  • 38
  • 80
1

What you're dealing with is are the fine-grained aspects of floating point numbers:

Computers save floating point numbers in a binary format. Your float is probably a IEEE-754 single precision floating point number.

In those formats, you can typically represent only numbers exactly that are only a sum of a very limited amount of powers of two; for example, 0.75 is 2-1 + 2-2 and can hence be exactly reconstructed. In your case, you try to divide 100 = 26 + 25 + 22 by 3 = 21+20 and hope you get exactly the same result as 0.3 = 2-2+ 2-5+ 2-9+ 2-10+ 2-13+ ...

That won't happen.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • Thank-you. I multiplied the ratio by 100 before, and changed the variable from float to integer. Now there is no rounding error to deal with. I wish Xcode would warn of such things... –  Apr 09 '15 at 21:33
  • Suggest 754, not 755. "single precision" is not specific enough as there are both binary and decimal single precision 754 formats. Certain you want [binary32](http://en.wikipedia.org/wiki/Single-precision_floating-point_format#IEEE_754_single-precision_binary_floating-point_format:_binary32) – chux - Reinstate Monica Apr 09 '15 at 22:08
  • @chux: you're right, I fixed that typo. I did not want to be so specific, because it really makes sense to read the introduction to that wikipedia page for OP. – Marcus Müller Apr 09 '15 at 22:11