【问题标题】:Fmod function clearly outputs an expected double, yet if(fmod == expected double) doesn't evaluate to true [duplicate]Fmod 函数清楚地输出预期的双精度,但 if(fmod == 预期的双精度) 不会评估为真 [重复]
【发布时间】:2018-09-01 15:28:45
【问题描述】:

当我调用我的函数时:

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 语句,但任何带有小数的东西都会让事情变得冒险。

【问题讨论】:

  • 您没有正确比较两个浮点值。比较它们的正确方法是检查它们的差异是否在某个delta 之内,其中delta 表示您愿意为您的应用程序容忍的误差范围。原因是大多数浮点值不能用二进制精确表示。
  • 据我所知,浮点类型的变量和文字不应该直接比较。
  • 正如@MikeBorkland 所说,这也是您从不使用浮点数换取现金的原因之一。而是使用整数。
  • @MikeBorkland -- 比较浮点值是否相等的正确方法是比较它们是否相等。检查它们是否“几乎相等”会引入许多其他问题;这不是一个简单的替代品。
  • 请注意,仅添加 epsilon 是不够的,浮点比较远不止于此。阅读Comparing Floating Point Numbers, 2012 EditionWhat is the most effective way for float and double comparison?

标签: c++ floating-point comparison


【解决方案1】:

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

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

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

Math.abs(d1 - d2) <= some_small_delta

另见:JUnit assertEquals(double expected, double actual, double epsilon)

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

另见:

【讨论】:

    猜你喜欢
    • 2021-01-20
    • 2011-02-01
    • 2016-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多