【问题标题】:Qt convert to double without added precisionQt 转换为双精度而不增加精度
【发布时间】:2023-12-23 14:09:01
【问题描述】:

我看过很多关于四舍五入的问题,但它们都涉及将一个数字四舍五入到最接近的整数或某个点数。我想要做的只是将一个字符串转换为双精度而不在小数点右侧添加任何数字。这是我现在的代码和结果:

将字符串 0.78240 转换为双精度值,它应该是 0.78240,但当我在调试器中查看它时却是 0.78239999999999998。

字符串值是一个 QString,只需使用 toDouble() 函数即可转换为双精度值。

我不明白这些额外数字是如何或从哪里来的,但如果能帮助我直接从 QString 转换为 double 将不胜感激!

【问题讨论】:

  • 可以在 IEEE 754 64 位二进制中精确表示的最接近 0.78240 的数字是 0.78239999999999998436805981327779591083526611328125。除了选择最接近十进制字符串的可表示数字之外,我不确定您希望 Qt 做什么。
  • 那么,0.78240这个数字是不是不能准确表示呢?原谅我对这个话题的无知......如果我继续使用它最接近的表示,所有基于它的计算都会采用相同的形式吗??
  • @PatriciaShanahan : 这不是 Qt 问题,显示的值是由调试器显示的。
  • @Alan 正确。发生这种情况是因为浮点使用二进制格式,它只能表示二进制分数的有限子集。就像没有完全等于 1/3 的小数一样,也没有完全等于 1/10 的二进制小数。
  • @PatriciaShanahan :这是一个有价值的答案的核心 - 考虑回答而不是评论。

标签: qt double rounding


【解决方案1】:

额外的数字是因为您将十进制实数数转换为二进制浮点数

实数不同,浮点表示具有无限的分辨率和有限的范围,而且二进制浮点值并不完全符合所有(甚至大多数) 十进制实数值。

简单的事实是 二进制浮点 不能完全表示 0.7824010,您的调试器在将二进制值往返返回到十进制。

这不一定是个问题,因为与值的大小相比,误差非常小,而且无论如何原始 0.78240 值无疑是现实世界值的某种近似值——它们都是近似值,只是二进制或十进制近似值。

该问题通常在演示而不是代表时处理。例如,在这种情况下,与必须显示内部表示的完整精度的调试器不同(您不希望在调试器中以任何其他方式显示),呈现此类值的标准方法会将其自身限制为很小,或者调用者定义的小数位数,即使显示到小数点后 15 位,该值也将正确显示为 0.782400000000000(默认情况下,标准输出方法将仅显示 0.7824)。

任何double呈现 15 个有效小数 或更少将按预期显示,对于float,这将减少到仅6 个有效数字。我想您的调试器正在显示更多数字,这些数字可以准确地以 IEEE 754 64 位 FP(双精度)值呈现,因为 x86 FPU 在内部使用 80 位表示。

你真的是在为这些小事大汗淋漓。

这种表现形式的差异确实很重要的一个地方是金融应用。对于那些,通常使用 十进制浮点 并且通常使用比double 可以提供的更多有效数字。但是十进制浮点通常不在硬件中实现,因此速度要慢得多。此外,大多数编程语言不直接支持十进制浮点,需要库支持。 C# 是内置支持十进制浮点的语言示例;它的decimal 类型适用于 28 位有效数字。

【讨论】: