准确详解:CC++float、double数据类型的表⽰范围及精度
今天复习C++遇到了float、double数据类型的表⽰范围及精度问题,花费了⼀些时间重新梳理了⼀遍,鉴于⽹上很多⽂章写的并不清晰,并且有不少疏漏错误之处,特结合个⼈理解仔细整理如下。
要弄清楚这个问题,⾸先要搞清楚浮点数在内存中的存储⽅式。浮点数,区别于定点数,指的是⼩数点位不确定的的数据类型,其原理是将⼀个浮点数a⽤两个数m(尾数)和e(指数)来表⽰:a = m × b^e。其中的b为选取的基数。科学计数法就是⼀种特殊形式的浮点数。
在计算机⼆进制表⽰中,浮点数采⽤2作为基数,规定尾数的范围为1.0~2.0之间。
以float类型为例,根据最⼴泛采⽤的IEEE754标准规定,float数据类型长度为32位,其中最⾼位为符号位,中间8位为指数位,最后23位作为尾数位。
最⾼位符号位通过0/1来区分正负,0正1负;指数位则规定采⽤移码的形式存储,这样可以保证指数部分为⽆符号数,⽅便⽐较⼤⼩。移码表⽰法是在数X上增加⼀个偏移量来定义的,如果机器字长为n,规定偏移量为2^(n-1),对于8位补码-128~127,可得到对应的阶码表⽰为0~255,其中全0和全1分别⽤来表⽰0和⽆穷⼤,故规定1~254⽤来表⽰规范数字,即对应指数范围从-126到127;尾数部分统⼀规定为1.0-2.0之间,最⾼位必然为1,故可以省略,所以尾数部分从⼩数点后算起,最⼩可以取到1,最⼤则取
浮点数的基数什么意思
到⼆进制1(⼩数点后23位),即取到2-2^-23,可近似约等于2。故得到float绝对值的最⼤值取到2^127*(2-2^-23)约等于2^128=3.4E+38。加上符号之后可得float表⽰范围为(-3.4E+38)~(3.4E+38)。当然实际是取不到的,开区间。绝对值最⼩则可以取到2^-127*1,即为1.175E-38。
接下来解释精度。由于尾数部分位数是固定的⼩数点后23位,23位所能表⽰的最⼤数是2^23−1=8388607,所以⼗进制的尾数部分最⼤数值是8388607,也就是说尾数数值超过这个值之后,float将⽆法精确表⽰,所以float最多能表⽰⼩于8388607的⼩数点后7位,但绝对能保证的为6位,也即float的⼗进制的精度为为6~7位。
double数据类型的推算过程和上述同理,唯⼀的区别在于尾数由23位扩展到52位,阶码由8位增加到了11位,计算⽅法不变。所以double的阶码(移码表⽰)为1~2046,偏移量为1023,故指数范围为-1022~1023,得表⽰范围为(2^1023*2)~(-2^1023*2)即为-1.7E+308~1.7E+308,绝对值最⼩可以取到2^-1022,精度则为2^52-1=4503599627370495,为16位。所以精度最⾼位16位,⼀定可以保证15位。