使用下面给出的C代码(用Visual Studio编写):
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
float i = 2.0/3.0;
printf("%5.6f", i);
return 0;
}
产生输出: 0.666667
然而,当%5.6f更改为%5.20f时,输出更改为: 0.66666668653488159000
我的问题是为什么类似小数的输出会有细微的变化?
答案 0 :(得分:5)
当您使用32位浮点数时,计算机将2./3.
的结果表示为11,184,811 / 16,777,216,这正好是0.666666686534881591796875。在您使用的浮点数中,数字总是表示为某个整数乘以2的幂(可能是2的负幂)。由于对整数的大小有限(当使用float
时,整数必须适合24位,不包括符号),最接近2/3的可表示值是11,184,811 / 16,777,216。
printf
'%5.6f`显示“0.666667”的原因是“%5.6f”仅请求六位数,因此该数字以第六位数字舍入。
printf
%5.20f
显示“0.66666668653488159000”的原因是您的printf
实施“在17位数之后放弃”,从某种意义上说这足够接近。 printf
的某些实现(人们可能认为更好)会按照请求的格式允许打印所表示的值。在这种情况下,它们将显示“0.66666668653488159180”,如果您请求更多数字,它们将显示确切的值“0.666666686534881591796875”。
(浮点格式通常表示为符号,1 [包含]和2 [不包含]之间的分数,以及指数,而不是符号,整数和指数。数学上,它们是与指数中的调整相同:每个数字可用符号表示,24位无符号整数和指数等于带符号的某个数字,1到2之间的分数以及调整后的指数。使用整数版本倾向于使证明更容易,有时有助于解释。)
答案 1 :(得分:2)
与可以在任何基数中精确表示的整数不同,相对较少的小数部分具有基本2分数格式的精确表示。
这意味着FP整数是精确的,并且通常FP分数不是。
因此对于两位数,例如0.01到0.99,只有0.25,0.50和0.75(和0)具有精确的表示。通常情况下,输出被舍入无关紧要,实际上,如果格式中可用的精度已知任何物理常数,则无关紧要。
答案 2 :(得分:0)
这是因为你可能没有浮点数的精确表示0.6666666666666666 ... 66667。
答案 3 :(得分:0)
精度以指数格式存储,即像( - / +)ax10 ^ n。如果数据类型是32位,则将1比特用于符号,8比特用于a,而休息用于n。因此,它不会在点后20位后存储值。因此,在此编译器中,您将永远无法获得正确的值。
答案 4 :(得分:-1)
float类型只有23位表示小数部分,20表示太多。