最近在学习Linux必然逃不开C语言,在格式化输入输出的时候遇到%f和%g。通过查阅《深入理解计算机系统》,总结如下。
二进制小数
先说下十进制小数 dmdm−1…d1d0.d−1d−2…d−n 其中每个十进制数的取值范围是0-9。这个表示法描述的数值 d 定义如下:
d=∑i=−nm10i∗di 相应的二进制小数 bmbm−1…b1b0.b−1b−2…b−n 其中每个二进制数取值范围是0-1。同样的,这个表示法描述的数值定义如下:
b=∑i=−nm2i∗bi考虑有限长度编码,两种表示法都无法表达实数,甚至是有理数,比如前者无法表示1/3,后者不能表示0.2。
浮点数
浮点数是相对于定点数而言的,所谓浮点数就是小数点浮动的数,通过小数点的浮动提高机器的数据表示能力。大多数机器对整数使用补码编码而对浮点数使用IEEE浮点编码,IEEE浮点编码是一个浮点编码的标准。它用如下形式来表示一个数值:
V=(−1)S∗M∗2E
S 是符号位,M 是尾数,它是一个二进制小数,它的范围是 2−ϵ 或者 1−ϵ (之所以这样规定,是出于更好的表示),E是阶码,它的作用是给 M 加权,2的E 次幂(可能是负数)。在值的位表示已定,比如单精度,之后通过分类(分成规格化、非规格化,特殊值),进一步映射到实数,从而更好的表示数值。单精度浮点数
用32位表示浮点数,其中1位符号位,23位尾数,8位阶码。
双精度浮点数
用64位表示浮点数,其中1位符号位,52位尾数,11位阶码。
浮点运算
有了浮点数,进一步有浮点运算,浮点运算是为了映射实数运算。由于浮点数不能完全表示实数,很多实数需要进行舍入(rounding),IEEE定义了四种不同的舍入方式。默认的方法是找到最接近的匹配,而其它三种可用于计算上下界。当进行浮点运算时,IEEE标准定义了一个简单的规则,用来确定诸如加法和乘法这样的算术运算的结果。即把浮点值x和y看成实数,而某种运算*定义在实数上,计算将产生round(x*y),这是对实际运算的精确结果进行舍入的结果。这样给了运算的软硬件实现者运用各自方法的机会。
C语言下浮点数
C语言不要求使用IEEE标准,大部分实现基本类似IEEE标准,但是不同的系统可能有差异。