1 前言
咱们在学习 C 语言时,通常认为浮点数和小数是等价的,并没有严格辨别它们的概念,这也并没有影响到咱们的学习,起因就是浮点数和小数是绑定在一起的,只有小数才应用浮点格局来存储。
其实,整数和小数能够都应用定点格局来存储,也能够都应用浮点格局来存储,但理论状况却是,C 语言应用定点格局存储整数,应用浮点格局存储小数,这是在“数值范畴”和“数值精度”两项重要指标之间谋求均衡的后果。
2 什么是浮点数?
浮点型简略讲就是实数的意思。浮点数在计算机中用以近似示意任意某个实数。具体的说,这个实数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是 2)的整数次幂失去,这种示意办法相似于基数为 10 的迷信记数法。
3 浮点数在内存中的存储
首先明确一点,无论是整型、浮点型还是字符等等数据类型在计算机底层都是以二进制的形式存储的。
浮点数在内存中的存储和整数不同,因为整数都能够转换为一一对应的二进制数据。而浮点数的存储是由符号位 (sign) + 指数位 (exponent) + 小数位 (fraction) 组成。
int 和 float 同样占据四个字节的内存,然而 float 所能示意的最大值比 int 大得多,其根本原因是 浮点数在内存中是以指数的形式存储
。
浮点数转换到内存中存储的步骤分为如下三步:
- 将浮点数转换成二进制
- 用迷信计数法示意二进制浮点数
- 计算指数偏移后的值
对于第 3 点:计算指数时须要加上偏移量(前面有介绍为什么应用偏移量),而偏移量的值与浮点数的类型无关(float 偏移量值为 127,double 偏移量值为 1023)。比如对于指数 6,float 与 double 类型偏移后的值别离为:
- float : 127 + 6 = 133
- double:1023 + 6 = 1029
4 实例
浮点数 19.625 用 float 是如何存储的:
- 将浮点数转换成二进制:10011.101(将 19.625 整数局部采纳除 2 取余,小数局部采纳乘 2 取整法);
- 用迷信计数法示意二进制浮点数:
1.0011101*2^4
; - 计算指数偏移后的值:127 + 4 = 131(10000011);
- 拼接综上所述,float 类型的 19.625 在内存中的值为:0 – 10000011 – 001 1101 0000 0000 0000 0000。
5 float 与 double 范畴和精度
范畴
float
和 double
的范畴是由指数的位数来决定的。(因为示意的时候都是 1.x * 2^Y
的模式,所以疏忽了 1.x
的成果,间接取指数示意浮点数的范畴)
- float:
1bit(符号位)8bits(指数位)23bits(尾数位)
- double:
1bit(符号位)11bits(指数位)52bits(尾数位)
于是,float
的指数范畴为 -127~+128
,而double
的指数范畴为-1023~+1024
,并且指数位是按补码的模式来划分的。
其中负指数决定了浮点数所能表白的绝对值最小的非零数;而正指数决定了浮点数所能表白的绝对值最大的数,也即决定了浮点数的取值范畴。
float
的范畴为-2^128 ~ +2^128
,也即-3.40E+38 ~ +3.40E+38
;
double
的范畴为-2^1024 ~ +2^1024
,也即-1.79E+308 ~ +1.79E+308
。
精度
float
和 double
的精度是由尾数的位数来决定的,尾数越多能示意的小数点前面有效数字就越多,因而精度就越高。浮点数在内存中是按迷信计数法来存储的,其整数局部始终是一个隐含着的“1”,因为它是不变的,故不能对精度造成影响。
float:2^23 = 8388608
,一共七位,这意味着最多能有 7 位有效数字,但相对能保障的为 6 位,也即 float
的精度为 6~7 位有效数字;
double:2^52 = 4503599627370496
,一共 16 位,同理,double
的精度为 15~16 位。
6 解剖:为什么要用偏移量的形式来计算指数?
如果不采纳偏移量的形式:
8 位 2 进制数示意的有符号数范畴有两个区间:0000 0000~0111 1111
和 1000 0000~1111 1111
,别离为0~+127
和-127~0
。
大家看到这里的问题了吧,有两个 0,一个正 0 和一个负 0。
如果采纳偏移量的形式:
127 转化为二进制是:0111 1111
那么
- 当咱们要示意 -127,则有
127-127
即0111 1111 - 0111 1111 = 0000 0000
- 当咱们要示意 -126,则有
127-126
即0111 1111 - 0111 1110 = 0000 0001
- 当咱们要示意 -2,则有
127-2
即0111 1111 - 0000 0010 = 0111 1101
- 当咱们要示意 -1,则有
127-1
即0111 1111 - 0000 0001 = 0111 1110
- 当咱们要示意 0,则有
0+127
即0000 0000 + 0111 1111 = 0111 1111
- 当咱们要示意 1,则有
1+127
即0000 0001 + 0111 1111 = 1000 0000
- 当咱们要示意 2,则有
1+127
即0000 0010 + 0111 1111 = 1000 0001
当咱们要示意 128,则有 128+127 即 1000 0000 + 0111 1111 = 1111 1111
由下面的例子,咱们能够得出法则,采纳移位存储技术,咱们能够应用 8 位二进制来示意从 -127~+128
共计 127 个正数 + 零(0)+ 128 个负数总共 256 个数,看来应用移位存储既没有 +0 和 -0 的问题,又能充沛应用新生成的 8 位二进制数最大限度的示意单精度浮点数的幂指数,是十分正当的。