C语言 将货币值作为浮点数进行比较不起作用



如果我键入 0.01 或 0.02,程序会立即退出。我该怎么办?

#include <stdio.h>
char line[100];
float amount;
int main()
{
printf("Enter the amount of money: ");
fgets(line, sizeof(line), stdin);
sscanf(line, "%f", &amount);
if (amount == 0.0)
    printf("Quarters: 0nDimes: 0nNickels: 0nPennies: 0");
if (amount == 0.01)
   printf("Quarters: 0nDimes: 0nNickels: 0nPennies: 1");

if (amount == 0.02)
   printf("Quarters: 0nDimes: 0nNickels: 0nPennies: 2");
return (0);
}

浮点数和双重比较最有效的方法是什么?

你应该使用这样的东西

bool isEqual(double a, double b)
{
    return fabs(a - b) < EPSILON;
}

或者这个

#define ISEQUAL(a,b) ( fabs((a) - (b)) < EPSILON)

并定义 EPSILON

#define EPSILON (0.000001)

首先,不要试图比较double s,或者比较float s,或者比较double s和float s(例外:与0比较是可以的,可以说是所有整数)。其他答案给出了很好的链接,但我特别喜欢:http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

其次,如果您正在处理一笔钱,请不要使用double,或者尽快摆脱double。要么使用定点库(对于你想要的有点复杂),要么干脆做:

int cents = (int)round(amount * 100);

然后改用cents。您可以将这些与你内心的内容进行比较。

第三,如果这里的想法是计算季度、一角钱、镍币和便士的变化,那么收集if语句不是要走的路,除非你喜欢冗长而低效的程序。您需要以编程方式执行此操作。如果你有上面的cents整数,这将容易得多(提示:查看%运算符)。

我认为

我们可以针对一个因素进行缩放并进行这样的相对比较:

#define EPSILON (0.000001)
if (fabs(a - b) <= EPSILON * fmax(fabs(a), fabs(b))) {
}

这比绝对比较更可靠:

if (fabs(a - b) <= EPSILON ) {
    // ...
}

这可能取决于规模。顺便说一下,具有最佳比例也取决于函数,我们不应该对日志和罪恶使用相同的公式。

这个答案的反对票是当之无愧的,它错误地提倡一个简单的平等测试。虽然这是未定义的行为,不应鼓励,但即便如此,它有时也会起作用。

切勿测试浮点值的相等性。相反,请使用 epsilon 值针对某个范围测试您的变量,因为这个答案暗示了它。

举个例子:

#include <stdio.h>
#include <math.h>
#define  EPSILON 0.00001f
int main() {
    float a = 3.234324333f;
    float b = a;
    b += 1;
    b -= 1;
    
    printf("a value is %fn", a);
    printf("b value is %fn", b);
    printf("na == b ?n");
    if (a == b) {
        printf("truen");
    } else {
        printf("falsen");
    }
    printf("a ~= b with epsilon = %f ?n", EPSILON);
    if (fabs(a - b) <= EPSILON) {
        printf("truen");
    } else {
        printf("falsen");
    }
    return 0;
}

运行时:

a value is 3.234324
b value is 3.234324
a == b ?
false
a ~= b with epsilon = 0.000010 ?
true

最新更新