【问题标题】:float overflow?浮动溢出?
【发布时间】:2011-03-15 05:36:00
【问题描述】:

以下代码似乎总是产生错误的结果。我已经在 gcc 和 windows visual studio 上对其进行了测试。是因为浮动溢出还是其他原因?在此先感谢:)

#include <stdio.h>
#define N 51200000
int main()
{
 float f = 0.0f;
 for(int i = 0; i < N; i++)
  f += 1.0f;
 fprintf(stdout, "%f\n", f);
 return 0;
}

【问题讨论】:

  • 请澄清您所说的“错误结果”是什么意思:您的预期结果是什么?您的实际结果是什么?
  • @AakashM:预期结果为 51200000;实际结果会少很多。我还没有运行代码,但我猜实际结果类似于 16777216。
  • 正如 Mike 所说,预期结果是 51200000,实际结果是 16777216。抱歉,不清楚。
  • 学到了很多,非常感谢大家!

标签: c++ c


【解决方案1】:

在编辑您问题中的代码时,我遇到了一个未阻止的for loop

#include <stdio.h>
#define N 51200000
int main() {
    float f = 0.0f;

    for(int i = 0; i < N; i++) {
        f += 1.0f;
        fprintf(stdout, "%f\n", f);
    }

    return 0;
}

【讨论】:

    【解决方案2】:

    您的问题是unit of least precision。短:大浮点值不能用小值递增,因为它们将四舍五入到下一个有效浮点数。虽然 1.0 足以增加小值,但 16777216 的最小增量似乎是 2.0(检查了 java Math.ulp,但也适用于 c++)。

    Boost 对this 有一些功能。

    【讨论】:

      【解决方案3】:

      与浮点运算有关的不可靠的事情包括当两个数字的大小相差很大时将它们相加,而当它们的大小相似时将它们相减。首先是你在这里做什么; 1

      【讨论】:

      • 这正是我遇到的问题。总结许多小的实数有点棘手。谢谢:)
      【解决方案4】:

      有关 C 中数据类型精度的更多信息,请参阅this

      当您超出定义的精度时,您的代码会出现异常行为。

      【讨论】:

        【解决方案5】:

        float 的精度只有 7 位。将数字 1 添加到大于 2^24 的浮点数会产生错误的结果。使用double 类型而不是float,您将获得正确的结果。

        【讨论】:

          【解决方案6】:

          float 只有 23 位精度。 512000000 需要 26。简单地说,你没有正确答案所需的精度。

          【讨论】:

          • 其实512000000不需要26位,就是15625 * 2^15。因此,您需要 14 位精度和 4 位指数。实际问题是 511999999 需要 26 位精度。
          • Getting 到 512000000。不管怎样,这都是个问题。
          • 更有趣的是,两个打印函数输出的结果相同:#define N 51200000 f = float(N); fprintf(stdout, "%.7e\n", f); for(int i = 0; i
          • 实际上浮点数有 24 位精度(23 存储 + 1 隐藏)。
          • @MSalters 浮点数总是被规范化的(非规范化除外)。 5.12e+8 用二进制写成 1.1110 1000 0100 1 e+11100,指数需要 6 位(符号需要 5 + 1)。
          猜你喜欢
          • 1970-01-01
          • 2021-06-04
          • 2013-04-09
          • 2012-09-20
          • 2023-03-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-16
          相关资源
          最近更新 更多