如何准确地将 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);
我有一个代表单价的 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);