【问题标题】:what's is going wrong with this loop condition? [duplicate]这个循环条件出了什么问题? [复制]
【发布时间】:2014-02-15 23:13:57
【问题描述】:

查看this link 的输出(向下滚动查看输出)以了解我要完成的工作

问题在于第 9-11 行的 for 循环

for(i=0; i<=0.9; i+=0.1){
  printf("%6.1f ",i);
}

我预计这会打印从 0.0 到 0.9 的值,但在打印 0.8 后它会停止,知道为什么吗??

【问题讨论】:

标签: c


【解决方案1】:

理想情况下,浮点不应该用于迭代,但如果您想知道为什么要更改代码并看看如何。

for(float i=0; i<=0.9f; ){
    i+=0.1f;
    System.out.println(i);
}
    

这是结果。

0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001

您的第 9 个值超过 0.9。

【讨论】:

  • 是的,但是 C 中的 0.9 不也超过 0.9 相同的数量吗?
  • 是的,这里的区别是,增量是在打印值之前。
  • 实际上这里的关键是由于求和导致的错误累积 - 请参阅我在测试用例中的答案
【解决方案2】:

浮点数不能精确表示小数,所以舍入误差会累积:

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    float literal = 0.9;
    float sum = 0;
    for(int i = 0; i < 9; i++)
        sum += 0.1;

    cout << setprecision(10) << literal << ", " << sum << endl;
    return 0;
}

输出:

0.8999999762, 0.9000000954

【讨论】:

    【解决方案3】:

    浮点运算在计算中是不精确的。这是因为计算机表示浮点值的方式。以下是 MSDN 关于该主题的文章的摘录:

    每一个十进制整数都可以用二进制整数精确表示;但是,对于小数来说,这不是 > 正确的。事实上,每一个以 10 为底的无理数在任何底数小于 10 的系统中也将是>无理数。

    对于二进制,特别是,只有可以以 p/q 形式表示的小数,>其中 q 是 2 的整数幂,可以用有限的位数精确表示。

    即使是常见的小数,例如十进制 0.0001,也不能用 >binary 精确表示。 (0.0001 是一个重复的二进制小数,周期为 104 位!)

    全文链接:https://support.microsoft.com/kb/42980

    【讨论】:

      【解决方案4】:

      在这里使用浮点数是问题的根源。相反,请使用 int:

      int i;
      for(i = 0; i <= 10; i++)
         printf("%6.1f ", (float)(i / 10.0));
      

      输出:

      0.0    0.1    0.2    0.3    0.4    0.5    0.6    0.7    0.8    0.9    1.0 
      

      【讨论】:

        【解决方案5】:

        你的循环是对的,但循环中的浮点比较并不安全。 问题是binary floating point number cannot exactly represent 0.1

        这会起作用。

            for(i=0.0; i<=0.9001; i+=0.1){
                   printf("%6.1f ",i);
        

        【讨论】:

          猜你喜欢
          • 2011-02-06
          • 1970-01-01
          • 2014-12-26
          • 2018-04-06
          • 1970-01-01
          • 2013-03-13
          • 1970-01-01
          相关资源
          最近更新 更多