关于C#:这个循环条件出了什么问题?


what's is going wrong with this loop condition?

本问题已经有最佳答案,请猛点这里访问。

查看此链接的输出(向下滚动查看输出),以了解我正在尝试实现的目标。

问题出在9-11号线的for环路上。

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

我希望它能打印0.0到0.9之间的值,但它在打印0.8之后就停止了,知道为什么吗??


在这里使用float是问题的根源。相反,使用int:

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

输出:

1
0.0    0.1    0.2    0.3    0.4    0.5    0.6    0.7    0.8    0.9    1.0

作为答案添加,因为没有足够的声誉发表评论。

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

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

这是结果。

1
2
3
4
5
6
7
8
9
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001

您的第9个值超过0.9。


浮点数不能精确地表示小数,因此舍入错误会累积:

1
2
3
4
5
6
7
8
9
10
11
12
13
#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;
}

输出:

1
0.8999999762, 0.9000000954


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

Every decimal integer can be exactly represented by a binary integer; however, this is not >true for fractional numbers. In fact, every number that is irrational in base 10 will also be >irrational in any system with a base smaller than 10.

For binary, in particular, only fractional numbers that can be represented in the form p/q, >where q is an integer power of 2, can be expressed exactly, with a finite number of bits.

Even common decimal fractions, such as decimal 0.0001, cannot be represented exactly in >binary. (0.0001 is a repeating binary fraction with a period of 104 bits!)

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


循环是正确的,但是循环中的浮点比较不安全。问题是二进制浮点数不能精确表示0.1

这是可行的。

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