如何准确地将 COleCurrency 乘以 double?

How to accurately multiply a COleCurrency by a double?

我有一个代表单价的 COleCurrency 对象。我有一个代表数量的 double 值。我需要计算总金额,精确到一分钱。

看起来 COleCurrency 内置了乘法运算符,但仅适用于与 long 值的乘法运算。

我可以将 COleCurrency.m_cur.int64 乘以 double,但这会将 double 转换为 __int64,因此它不准确。

准确地将 COleCurrency 乘以 double 的最佳方法是什么?

有限二进制浮点值构成有限十进制值的真子集。虽然任何给定的浮点值都有精确的、有限的十进制表示,但反之则不然。换句话说,并不是每个小数都可以使用有限的二进制浮点值来表示。一个简单的示例是 0.1,它在转换为二进制浮点值时产生 无限 二进制数字序列。

这里的重点是,如果您要处理小数值,使用二进制浮点值来表示它们通常会导致不准确(非常 少数例外,例如0.5)。与整数值进行精确乘法的唯一方法是使用整数作为被乘数。

既然您选择使用浮点值,那么您唯一能做的就是限制不准确性。建议的解决方案:

__int64 x = currency.m_cur.int64 * (__int64)dbl;

遇到编译器警告的相同 “可能丢失数据” 问题。由于您现在使用的是显式强制转换,因此这会使编译器静音。效果仍然相同:浮点值被截断。

更好的方法是先将 64 位整数值转换为 double。这将生成整数值的 exact 浮点表示,前提是它在范围内(大约 +/- 1e15)。然后,您可以乘以另一个浮点值(会出现舍入误差),最后使用 std::llround:

对结果进行舍入
__int64 x = std::llround(static_cast<double>(currency.m_cur.int64) * dbl);