Fmod函数显然会输出预期的两倍,但是如果(fmod ==预期的两倍)的计算结果不为true

时间:2018-09-01 15:28:46

标签: c++ floating-point comparison

当我调用函数时:

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语句,但是带小数的任何内容都会使事情变得扑朔迷离。

1 个答案:

答案 0 :(得分:2)

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

整本书中都有关于IEEE浮点编码的内容,但是对于初学者而言,任何Wikipedia文章都是一个不错的开始:https://en.wikipedia.org/wiki/Floating-point_arithmetic

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

double

另请参阅:JUnit assertEquals(double expected, double actual, double epsilon)

因此,如果两个数字之间的差足够小,则它们被视为相等。在货币方面,一种常见的选择是确定系统所需的最小面额(例如,当货币为“美元”时为“分”),并始终将“ 1美元”表示为具有价值的Math.abs(d1 - d2) <= some_small_delta int,而不是值为100的浮点。甚至还有一些库可以简化此任务,从而有效地对定点数据类型进行建模。

另请参阅: