简体   繁体   中英

I am not sure why my code is producing this arithmetic error?

Hey everybody I am working on a program in c that tells you the least number of coins needed for any given amount of money. I have a program written that works for for every amount I have tested except for $4.20.

Here is my code:

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

int main(void)
{
    float f;
    int n, x, y, z, q, s, d, t;

    do {
        printf("How much change do you need?\n");
        f = GetFloat();
    } while(f <= 0);

    {
        n = (f * 100);
    }

    q = (n / 25);
    x = (n % 25);
    y = (x / 10);
    z = (x % 10);
    s = (z / 5);
    d = (z % 5);
    t = (q + y + s + d);

    {
        printf("%d\n" ,t);
    }
}

The strange thing is when I input 4.20 the output is 22 instead of 18 (16 quarters and 2 dimes). I did some sleuthing and found that the problem is with my variable x. When I input 4.2, x gives me 19 and not 20 like it should. I tried other cases that I thought should have produced the same problem like 5.2 and 1.2 but it worked correctly in those cases. It might be a rounding issue but I would think that same error would also happen with those similar values.

Does anyone have an idea about why this might be happening?

PS I am fairly new to coding and I haven't gotten much formal instruction so I also welcome tips on better indentation and formatting if you see anything obvious.

IEEE 754 floating point is often slightly imprecise, and casting will truncate, not round. What's likely happening is that 4.20 * 100 evaluates to 419.999999999999994 (exact number is immaterial, point is, it's not quite 420), and the conversion to int drops the decimal portion, producing 419.

The simple approach is to just do:

n = f * 100 + 0.5;

or you can use a proper function:

n = round(f * 100);

If the number is "almost" exact, either one will be fine, you'd only get discrepancies when someone passed non-integer cents ( "4.195" or the like), and if you're using float for monetary values, you've already accepted precision issues in the margins; if you want exact numbers, you'd use the decimal formats that have fixed precision for decimal values, and are intended for financial calculations.

Try this: Provides up to 2 digit precision.

//float f
double f

f *= 1000;
f = floor(f);  /* optional */
f /= 10;
f = floor(f);  /* optional */
n = f;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM