为什么输出的差异?

时间:2013-06-17 15:27:55

标签: c floating-point

使用下面给出的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

我的问题是为什么类似小数的输出会有细微的变化?

5 个答案:

答案 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表示太多。