Fmod 函数清楚地输出一个预期的双精度值,但 if(fmod == 预期的双精度值)的计算结果不是 true

Fmod function clearly outputs an expected double, yet if(fmod == expected double) doesn't evaluate to true

本文关键字:双精度 true if fmod 结果 计算 Fmod 输出 清楚 函数 一个      更新时间:2023-10-16

当我调用我的函数时:

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 语句,但任何带有小数的内容都会让事情变得棘手。

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

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

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

Math.abs(d1 - d2) <= some_small_delta

另请参阅:JUnit assertEquals(双预期、双实际、双 epsilon(

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

另请参阅:

  • 以C++存储货币值的最佳方式
  • CNL:用于定点数据类型C++的组合数字库 (https://github.com/johnmcfarlane/cnl(