C - 打印怪异

时间:2013-12-05 11:46:48

标签: c random printf

编译代码时

#include <stdio.h>

int main() {
    int n, i, j;
    float broj;
    scanf("%d", &n);
    for (i=0; i<=n; ++i) {
        j=i;
        broj = 0.1 * j;
        while (j>=0) {
            printf ("%3.1f ", broj-(j*0.1));
            j--;
        }
        printf(" %d. red\n", i);
    }
    return 0;
}

在第5行开始打印第一个数字为-0.0而不是0.0,每第2行,所以它就像在第5,7,9等那样......

3 个答案:

答案 0 :(得分:4)

听起来像一些基本的浮点精度问题。请注意,0.1并不能完全表示为float,所以每次使用它时,您将使用它的近似值。

这意味着像你的代码一样使用0.1的重复计算也将重复近似误差,这可能会导致最终结果与您手动执行相同计算时的结果略有不同。

一如既往的好参考What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 1 :(得分:0)

在print语句中使用:

printf ("%3.1f ", broj-(float)(j*0.1));

答案 2 :(得分:0)

太了解发生了什么,你可以对你的程序做一点改动。根据默认参数,C标准printf()的促销规则将float提升为double。因此,我们可以看看double格式的操作中的数字发生了什么(更多的小数部分数字):

        while (j>=0) {
            printf ("%3.18lf ", j*0.1);
            printf ("%3.18lf ", broj);
            printf ("%3.18lf ", broj - j*0.1);
            /*printf ("%3.18lf ", (double)(broj-(j*0.1)));*/
                        break;
            j--;
        }

输出:

9
0.000000000000000000 0.000000000000000000 0.000000000000000000  0. red
0.100000000000000006 0.100000001490116119 0.000000001490116114  1. red
0.200000000000000011 0.200000002980232239 0.000000002980232228  2. red
0.300000000000000044 0.300000011920928955 0.000000011920928938  3. red
0.400000000000000022 0.400000005960464478 0.000000005960464455  4. red
0.500000000000000000 0.500000000000000000 -0.000000000000000028  5. red
0.600000000000000089 0.600000023841857910 0.000000023841857877  6. red
0.700000000000000067 0.699999988079071045 -0.000000011920928994  7. red
0.800000000000000044 0.800000011920928955 0.000000011920928911  8. red
0.900000000000000022 0.899999976158142090 -0.000000023841857960  9. red

输出显示由数字有限精度引起的效果。因此,第三列应该仅由零组成,但由于这种效应,它不会由零组成。