今天发生了一件奇怪的事情,当我尝试编译并执行此代码的输出并不是我所期望的。下面的代码只是将浮动值添加到float数组中,然后将其打印出来。 简单的代码:
int main(){
float r[10];
int z;
int i=34;
for(z=0;z<10;z++){
i=z*z*z;
r[z]=i;
r[z]=r[z]+0.634;
printf("%f\n",r[z]);
}
}
输出:
0.634000
1.634000
8.634000
27.634001
64.634003
125.634003
216.634003
343.634003
512.633972
729.633972
请注意,从.634之后的27个出现的数字应该不存在。谁知道为什么会这样?这是由浮点近似引起的事件?..
P.S我有一个linux debian系统,64位
感谢所有
答案 0 :(得分:5)
数字可以用以下形式表示:
[sign] [尾数] * 2 [指数]
当内存空间较小时,会出现舍入或相对错误。
来自wiki:
单精度浮点格式是计算机数字格式,在计算机内存中占用 4字节(32位),并使用浮点表示宽动态范围的值。
IEEE 754标准将binary32指定为:
Sign bit: 1 bit
Exponent width: 8 bits
Significand precision: 24 bits (23 explicitly stored)
这从 6到9有效十进制数字精度(如果a 最多6个有效小数的十进制字符串转换为IEEE 754单精度然后转换回相同的数量 有效小数,则最终字符串应与原始字符串匹配; 如果IEEE 754单精度转换为十进制字符串 至少有9个有效小数,然后转换回单个, 那么最终的数字必须与原来的[4]相匹配。
编辑(爱德华的评论):更大(更多位)的浮点表示允许更高的精度。
答案 1 :(得分:1)
是的,这是floating point近似误差或Round-off error。浮点数表示使用quantization来表示大范围的数字,因此它仅表示步骤并将所有中间数字舍入到最近的步骤。如果所需数字不是这些步骤之一,则会导致错误。
答案 2 :(得分:1)
除了其他有用的答案外,可以说明打印的数字多于默认数字:
int main(){
float r[10];
int z;
int i=34;
for(z=0;z<10;z++){
i=z*z*z;
r[z]=i;
r[z]=r[z]+0.634;
printf("%.30f\n",r[z]);
}
}
给出
0.634000003337860107421875000000
1.633999943733215332031250000000
8.633999824523925781250000000000
27.634000778198242187500000000000
64.634002685546875000000000000000
125.634002685546875000000000000000
216.634002685546875000000000000000
343.634002685546875000000000000000
512.633972167968750000000000000000
729.633972167968750000000000000000
请注意,0.634
实际上并不是#34; 0.634&#34;,而是float
代表的最接近的数字。
答案 3 :(得分:0)
“float”只有大约六位数的精度,所以你得到的错误并不意外。
如果使用“double”,则精度约为15位。你会出错,但你会得到125.634000000000003而不是125.634003。
因此,您总会得到四舍五入的错误,而您的结果将不会完全您所期望的,但通过使用双倍效果将是最小的。警告:如果您执行添加125 + 0.634然后减去125的操作,结果将(很可能)不为0.634。无论你使用float还是double。但是加倍,结果将非常非常接近0.634。
原则上,如果选择float和double,除非你有一个非常非常好的理由,否则你不应该使用float。