编译代码时
#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等那样......
答案 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
输出显示由数字有限精度引起的效果。因此,第三列应该仅由零组成,但由于这种效应,它不会由零组成。