我不知道为什么我的代码会产生这个算术错误?

时间:2022-09-04 08:34:35

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.

嘿,大家好,我正在用c语言编写一个程序,它告诉你们任何给定金额的货币所需的最小硬币数量。我有一个程序,它适用于我测试过的每一项,除了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.

奇怪的是,当我输入4.20时,输出是22,而不是18(16个25美分和2个10美分)。我做了一些调查,发现问题出在变量x上,当我输入4。2时,x得到19而不是20。我尝试过其他我认为应该产生类似于5.2和1.2的问题的案例,但在这些案例中它是正确的。这可能是一个四舍五入的问题,但我认为同样的错误也会发生在这些相似的值上。

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.

PS:我对编程相当陌生,也没有得到太多正式的指导,所以如果您看到任何明显的内容,我也欢迎您提供更好的缩进和格式化技巧。

2 个解决方案

#1


3  

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.

IEEE 754浮点数通常是不精确的,而且铸造会截断而不是圆的。可能发生的情况是,4.20 * 100的计算结果是419.999999999999994(确切的数字是不重要的,点是,它不是420),并且转换成int数的小数部分,产生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.

如果这个数字“几乎”是准确的,那么任何一个都是可以的,当一个人通过非整数的美分(“4.195”或类似的)时,你只会得到差异;如果你用浮点数来计算货币价值,你就已经接受了利润率的精确问题;如果你想要精确的数字,你可以使用具有十进制值的固定精度的小数格式,并用于财务计算。

#2


-2  

Try this: Provides up to 2 digit precision.

尝试这个:提供最多2位精度。

//float f
double f

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

#1


3  

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.

IEEE 754浮点数通常是不精确的,而且铸造会截断而不是圆的。可能发生的情况是,4.20 * 100的计算结果是419.999999999999994(确切的数字是不重要的,点是,它不是420),并且转换成int数的小数部分,产生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.

如果这个数字“几乎”是准确的,那么任何一个都是可以的,当一个人通过非整数的美分(“4.195”或类似的)时,你只会得到差异;如果你用浮点数来计算货币价值,你就已经接受了利润率的精确问题;如果你想要精确的数字,你可以使用具有十进制值的固定精度的小数格式,并用于财务计算。

#2


-2  

Try this: Provides up to 2 digit precision.

尝试这个:提供最多2位精度。

//float f
double f

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