【问题标题】:Losing precision in stringstream在字符串流中失去精度
【发布时间】:2016-05-30 00:16:30
【问题描述】:

在我的一个应用程序中,我试图将浮点值放入这样的字符串流中:

stream << static_cast<float>(double value);

我没有得到整个浮点值,而是只得到它的整数部分。知道为什么会发生这种情况吗?

【问题讨论】:

  • 您必须提供更多代码,以便人们可以看到实际发生的情况。如所写,此代码 sn-p 无法编译。您使用了什么值,以及将什么写入流?

标签: c++ floating-point floating-accuracy stringstream static-cast


【解决方案1】:

您正在转换为 float - C++ 将其定义为 IEEE 754 32-bit 'single precision' floating point type

如果您查找此类值的格式,则 32 位分为三个部分:

  • 23 位存储有效位
  • 8 位存储指数
  • 1 位存储符号。

如果您有 23 位来存储有效位,这意味着您可以在有效位中表示的最大值是 2^23。因此,单精度浮点数只有大约 6-9 位的精度。

如果您的浮点值在小数点前有 9 位或更多位 - 如果超过 2^23 - 您将永远不会有小数部分。

为了帮助理解,请考虑以下代码:

    void Test()
    {
        float test = 8388608.0F;

        while( test > 0.0F )
        {
            test -= 0.1F;
        }
    }

该代码永远不会终止。每次我们尝试将 test 减 0.1 时,幅度的变化都会丢失,因为我们没有存储它的精度,所以值最终回到 8388608.0。永远无法取得进展,因此它永远不会终止。所有有限精度浮点类型都是如此,因此您会发现同样的问题会发生在 IEEE 754 双精度浮点类型(64 位)上,只是值不同而已。

另外,如果您的目标是尽可能地保持精度,那么从 double 转换为 float 是没有意义的。 double 是 64 位浮点类型; float 是 32 位浮点类型。如果您使用双精度,如果您的值足够小,您可能能够避免大部分截断。

【讨论】:

  • C++ 标准没有float 定义为 IEEE 754 类型。这很常见,但不是必需的。
  • 这个答案没有解决问题。
  • @PeteBecker - 你能澄清一下吗?对任何人来说,投反对票和一句话“这是错误的”都不是很有帮助。除了我对 C++ floatdouble 类型的熵的错误假设之外,我不明白你的批评。我是否说错了,超过一定限制,浮点数不能再存储带有小数部分的值?我断言在这种情况下是问题所在是错误的吗?对于处理浮点数学时最常遇到的问题之一,我是否对提问者的问题阅读过多?
  • @antiduh - 阅读问题。虽然问题可能是值太大,但问题中没有任何内容表明情况如此。有太多其他可能性可以简单地断言这就是问题所在。
  • @PeteBecker - 你愿意说出/描述另一种可能性吗?
猜你喜欢
  • 2019-05-26
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 2014-01-13
  • 2022-11-01
  • 2011-03-17
相关资源
最近更新 更多