c++ - 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 语句,但任何带有小数的东西都会让事情变得冒险。
解决方案
浮点数据类型是有限的并且不精确。并且它们的编码方式使得初学者对于它们不精确的值非常不直观(例如0.5
,将精确表示,0.1
需要四舍五入)。
关于 IEEE 浮点编码的来龙去脉有整本书,但对于初学者来说,任何 Wikipedia 文章都是了解它的良好开端:https ://en.wikipedia.org/wiki/Floating-point_arithmetic
这个问题有不同的解决方案,具体取决于您的域,例如使用 MPFR(https://www.mpfr.org/)等任意精度库。大多数单元测试框架满足于不使用==
相等性,而是引入“足够接近”的比较。例如,JUnit 的assertEquals
fordouble
有效地检查以下内容:
Math.abs(d1 - d2) <= some_small_delta
另请参阅:JUnit assertEquals(双预期,双实际,双小量)
因此,如果两个数字之间的差异足够小,则它们被认为是相等的。在货币的上下文中,一种常见的替代方法是确定您的系统需要的最小面额(例如,当货币为“美元”时可能是“美分”)并始终将“1 美元”表示为int
有值100
而不是浮点数具有价值1.0
。甚至还有一些库可以简化这项任务,有效地对定点数据类型进行建模。
也可以看看:
- 在 C++ 中存储货币值的最佳方法
- CNL:具有定点数据类型的 C++ 组合数值库 ( https://github.com/johnmcfarlane/cnl )
推荐阅读
- npm-install - 错误:EPERM:不允许操作,mkdir 'C:\Users\xxxxxxx'
- python - 如何使用带有轮廓场、矢量场和移动框的 matplotlib 制作视频?
- javascript - 在点击 Javascript 之前执行按钮方法
- php - 加快大数据的高斯消除php代码
- javascript - 多次下载适用于网络,但不适用于移动设备
- java - 使用 BeanUtils.copyProperties 从 Mybatis 创建的对象到 Spring Bean,Spring bean 中的属性为空。为什么?
- arduino - arduino 作为 modbus RS485 从机向主机发送消息
- javascript - 如何在 Joi Schema 数据验证期间删除无效字段而不是返回错误?
- javascript - React - 使用带有条带 createPaymentMethod 的异步
- java - 为什么我们需要像下面这样的一些方法访问修饰符“静态”?