首页 > 解决方案 > Fmod 函数清楚地输出预期的双精度,但 if(fmod == 预期的双精度) 不会评估为真

问题描述

当我调用我的函数时:

formatCurrency(7.5);

string formatCurrency(double cash) {
cout << "fmod(cash,.1) is equal to " << fmod(cash,.1) << endl;
if(fmod(cash,1) == 0) {
    cout << cash << ".00";
}
else if(fmod(cash,.1) == 0.1) {
    cout << cash << "0";
}
else if(fmod(cash,.01) == 0.01) {
    cout << cash;
}
else{
    cout << "Error: unable to display in currency format";
}
return "";
}

fmod(7.5,.1) 显然等于 .1,当我运行程序时它甚至会输出。但相反,我得到以下输出:

fmod(cash,.1) is equal to 0.1
Error: unable to display in currency format

是什么赋予了?我认为我的代码没有任何问题。该代码确实适用于整数/第一个 if 语句,但任何带有小数的东西都会让事情变得冒险。

标签: c++floating-pointcomparison

解决方案


浮点数据类型是有限的并且不精确。并且它们的编码方式使得初学者对于它们不精确的值非常不直观(例如0.5,将精确表示,0.1需要四舍五入)。

关于 IEEE 浮点编码的来龙去脉有整本书,但对于初学者来说,任何 Wikipedia 文章都是了解它的良好开端:https ://en.wikipedia.org/wiki/Floating-point_arithmetic

这个问题有不同的解决方案,具体取决于您的域,例如使用 MPFR(https://www.mpfr.org/)等任意精度库。大多数单元测试框架满足于不使用==相等性,而是引入“足够接近”的比较。例如,JUnit 的assertEqualsfordouble有效地检查以下内容:

Math.abs(d1 - d2) <= some_small_delta

另请参阅:JUnit assertEquals(双预期,双实际,双小量)

因此,如果两个数字之间的差异足够小,则它们被认为是相等的。在货币的上下文中,一种常见的替代方法是确定您的系统需要的最小面额(例如,当货币为“美元”时可能是“美分”)并始终将“1 美元”表示为int有值100而不是浮点数具有价值1.0。甚至还有一些库可以简化这项任务,有效地对定点数据类型进行建模。

也可以看看:


推荐阅读