在Qt中,Float的加法不能给出精确的结果

Addition of Float does not give precise result in Qt

本文关键字:结果 不能 Qt Float      更新时间:2023-10-16

我正在应用程序中添加价格。我有QString s的值,我转换为浮点数和加法。当它达到高值时,结果不精确。我读到像float或double不应该用于货币加法,并为整数部分和小数部分使用单独的变量。我的代码和日志如下:

qDebug ("m_totalPrice: %f + %f =", m_totalPrice, item.price.toFloat());
m_totalPrice += item.price.toFloat();
qDebug ("m_totalPrice: %f", m_totalPrice);
ui->totalLabel->setText(QString::number(m_totalPrice, 'f', 2));  

m_totalPricefloat, item.priceQString

日志:

  1. m_totalPrice: 424659.500000 + 22350.500000 =
    m_totalPrice: 447010.000000

  2. m_totalPrice: 447010.000000 + 18.900000 =
    m_totalPrice: 447028.906250
  3. m_totalPrice: 447028.906250 + 125.900002 =
    m_totalPrice: 447154.812500
  4. m_totalPrice: 447154.812500 + 125.900002 =
    m_totalPrice: 447280.718750
  5. m_totalPrice: 447280.718750 + 11.500000 =
    m_totalPrice: 447292.218750
  6. m_totalPrice: 447292.218750 + 22500000 =
    m_totalPrice: 447314.718750

错误来自第2行。有人能告诉我如何解决这个问题吗?

编辑:既然我的问题不完整
第2行显示了447010.000000 + 18900000 = 447028.906250
我的疑问是,加起来至少应该是447028.9000.

这里有几个因素需要考虑。

  1. Float只有大约6位数的精度,这很容易超过。你可以通过使用double来解决这个问题,它给你大约15个数字。
  2. 存储为浮点数的十进制分数是近似值。当你把它们加起来时,误差会累积,当你减去它们时,就会失去精度。您可以通过将所有货币值存储为美分(而不是美元)甚至百分之一美分并根据需要转换/格式化来解决这个问题。
  3. 如果你这样做,那么无论何时你乘或除你必须四舍五入到最接近的整数(分或其他),以避免累积误差。

我在这里推荐的简单解决方案是使用双精度整数作为扩展精度整数,它可以找到最多15位数字或数万亿美元,以美分表示。

然而,如果你真的对货币计算很认真,你需要找到并使用Fixed Decimal算术包。你的投资是值得的。

我同意:永远不要使用float!