二进制(2):浮点数

来源:互联网 发布:qq群做淘宝客赚钱吗 编辑:程序博客网 时间:2024/05/21 07:56

一些数学符号的解释:
ϵ: 一个无限小的数,微积分中的一个概念。如果a=1-ϵ,
a的值无限接近于1。
:求和符号。5i=0xi=i5+i4+i3+i2+i1+i0
xi: x下标,此位(0或1)在位向量中的位置。(最右边为第0位)
[00000000]2: 下标2,表示进制。
:无穷。 a=+,a为无限大的一个数。 a=,a为无限小的一个数。
Cnk:不考虑顺序的组合。从n个元素中取k个元素,k个元素的组合数量为Cnk


浮点数,例如C语言的float与double,每天都会用,但是有很多人不知道为什么它被称为浮点,以及它表示的值是如何从1与0的机器代码中计算出来的。以下内容回答了几个基本问题,1,什么是浮点数?点是如何浮动的?浮点数的优势是什么?2,目前通用的IEEE754浮点数是如何计算的?3,如果浮点数被赋的值,例如运算结果或其他格式转换后的值不在浮点数可表示的范围之内会发生什么?4,同样数值的二进制代码在整数编码和浮点数编码中有什么区别?

1,什么是浮点数?点是如何浮动的?

为什么称为浮点数?什么是定点表示法?

“浮点”一词相对于“定点”,表示小数点是可移动的。先理解定点,在无符号编码中 1111 1111的值为27+26+25+24+23+22+21+20。为了让无符号编码也可以表示小数,可以规定让最低四位表示变量的小数部分,那么位向量1111 1111的值会变为23+22+21+20+21+22+23+24,这种位向量表示小数值的方法,通过规定从位向量的某一位开始由那一位的值乘以2的负数递减次幂,称为定点表示法,相当于在2021两个位之间写上了小数点,变为数学公式为,如果有位向量[bmbm1...b1b0b1b2...bn+1bn],则:

b=i=nm2ibi

无符号编码和补码编码也是属于定点表示法,只是他们的“小数点”是定在了最低位的右边。

浮点数的小数点是如何浮动的?

在定点表示法中,例如无符号编码,我们可以把[0000 0000]看做 [0000 0000.],最后面的小数点无论如何它的位置是不会变化的。但假设我们规定一个新的编码规则: 设变量 V的位向量在无符号编码下的值为E,而 V=2E。在这种编码模式下,小数点会发生什么变化? 假设V的位向量为[0000 0001],V=2[00000001]2=21=2,我们如果把小数点在最底层的机器代码中具象化出来,它是[0000 0001.]。如果V的位向量变为了[0000 0100],V=2[00000100]2=28=256,把小数点在最底层的机器代码中具象化出来,它是[0000 0100(000000).],小括号中的0并不存在于机器代码之中,它只是虚拟出来以理解小数点位置的。因此可以看出,在V=2E的这种编码模式下,随着变量V的位向量的值的不断变化,在它的位向量中,具象化出的小数点的位置也是不断变化的,这种小数点的浮动,也既是“浮点”,表达的其实是这种V=2E的编码模式中位向量所表示的值的变化规律。
再看一下目前各编程语言都在用的IEEE浮点标准:

V=(1)sM2E

公式中的2E也既是上面解释的为何它被称为“浮点”的原因。

浮点数相对于定点表示法的优势

1,在同样的位数中有更大的取值范围
定点表示法的缺点是它能表示的数值范围很小,在位向量有限的位数中既要表示整数又要表示小数,例如上面定义的[1111.1111],最低四位表示小数部分。它的最大值是23+22+21+20+21+22+23+24=15.9375 。如果用2E这种取值方式,它的整数部分最大可达2[1111]=28=2562100在无符号编码中需要101位才能表示,而在浮点编码模式下,2100=2[1100100]位向量只需要7位。

2,在同样的位数中可以更精确的表示小数
一组二进制位向量所能表示的小数数量是有限的,所以它只是一种模拟实数运算的方法,当给浮点数变量赋值为小数时,它的值将会是最接近被赋值的一个匹配值,一个位向量能表示的匹配值的多少可以理解为这个位向量的精度。定点表示法的第二个缺点是它能表示的匹配值很少,同样上面定义的1111.1111的小数部分只能表示21222324四个值组合出来的值,例如[0000.0001]=0.5, [0000.1001]=0.5+0.0625=0.5625,共有C04+C14+C24+C34+C44=241=15个数值。而在类似IEEE浮点的编码模式中,假设不考虑负数的情况,同样一个8位的位向量中,小数位为4位,整数位为4位,小数部分可以表示最多(C04+C14+C24+C34+C44)[1111]2=1515=225个数值。

2,目前通用的IEEE754浮点数是如何计算的?

以上假设的浮点数编码只是用来理解一些浮点数的概念,目前通用的IEEE754浮点数值的计算公式要更加复杂与精妙:

V=(1)sM2E1

一个32位的IEEE浮点数的位向量分为三个部分:

[0(符号位) 00000000(阶码位) 00000000000000000000000(小数位)]
从右起,0-23位为小数位,24-31位为阶码位,32位最高位为符号位。

符号位:符号位比较好理解,在公式1中,如果符号位为0,V的值就会为正,如果符号位为1,V的值就会为负。设符号位的值为s
阶码位:阶码位决定了V的取值范围,但它并不就是等于公式1中的E。设阶码位的值=exp,计算exp的值的方法采用无符号编码规则。
小数位设小数位的值=frac,计算frac的值的方法是也是定点数表示法, frac[e23e22e1e0]=e231+e222++e231+e240

计算IEEE浮点数值根据阶码的值分为三种情况:

在不同的情况中,公式1中的E与M的计算方式会有差异:

—情况1,阶码位非全0,并且非全1。这种情况下,浮点数的值被称为规格化的值。
—情况2,阶码位全0。非规格化的值。
—情况3,阶码位全1。特殊值。

先分析与比较32位的浮点数的情况1与情况2:

情况1中E与M的计算方法:
E=expBiasM=1+fracBias=211Bias:32127641024
情况2中E与M的计算方法:
E=1BiasM=fracBias=211Bias:32127641024

情况1之中,E的最小值是[00000001]2127=126,最大值为[11111110]212710=254127=127。M的最小值是1+[00...00]2=1,最大值为1+[11...11]=(2ϵ)非常接近2的一个值。所以V的最大值为,V=(1)0(2ϵ)2127=(2ϵ)1.70141183510383.41038,此时V的位向量是[0 11111110 11..11]。V的最小值为与最大值相比只是符号位变为了1,V=(1)1(2ϵ)21273.41038,V的位向量为[1 11111110 11..11]。V最接近0的值分别在0的两端,为V=(1)0112126=±2126

情况2之中,E的值是唯一的,1-127=-126。M的最小值是[00...00]=0,最大值为[11...11]=(1ϵ)一个非常接近1的值。V的最大值为,V=(1)0(1ϵ)21262126。V的最小值与最大值相比只是符号位变为了1,为(1)1(1ϵ)21262126。V的最接近0的值为0,[0 0000000 00…00]。

随着小数位的值的递增以及符号位的变化,匹配值均匀分布在数轴上0的两端,±2126之间,每两个匹配值的间距为223*。

比较情况1和情况2,有几个值得注意的点:
1,E:E决定了数值的取值范围,最小值,最大值,最接近0的正值,以及最接近0的负值。
2,±2126:这两个数值犹如一个边界,再数轴上,两个数值的之间为非规格化数值,两个数值之外规格化的数值。规格化的数值最接近0的值分别为V=(1)0112126=±2126,非规格化的最大最小值为V=(1)01(1ϵ)2126±2126。在这个边界处,E的值是固定的,-127。这种平滑的过渡是由M在规格化值中的最小值设定1+frac,以及frac的最大值为1ϵ 的特点所实现的。
3,小数位位数23:在数轴上,±2126之间平均分布着2231个小数匹配值,每两个匹配值之间的间距为2^{-23}。在±2126外侧,当frac值为0时,共有254个匹配值向数轴两端指数递增式的蔓延,在这些值中的每两个匹配值之间又有2231个匹配值,所以小数位的位数基本决定了浮点数的匹配值数量,浮点数的精度。

再看一下情况3,特殊值:

当阶码位全为1时,如果小数位全为0,此数表示无穷大,,而符号位决定了他是+。例如当一个float值除以0后它的值为无穷。
当阶码位全为1时,如果小数位不全为0,此数为NaN,not a number,不是一个数。两个值为无穷的float相减结果为NaN,如果一个float变量被赋值sqrt(-1),根号-1,它的值也会变为NaN。

3,如果浮点数被赋的值,例如运算结果或其他格式转换后的值不在浮点数可表示的范围之内会发生什么?

与一个整数变量不可能表示所有整数一样,一个浮点数也无法表示所有小数。因为浮点数根据长度与格式不同,它只能表示有限的匹配数,如果变量被赋的值不在这些匹配数之中,系统将会去寻找最接近的匹配值,也既是将变量被赋的值进行舍入。IEEE浮点数采用的舍入模式是“向偶数舍入”,这种舍入模式是寻找最接近的匹配值,如果被舍入的值正好在两个匹配数的正中间,将会寻找最接近的最低有效位为偶数的匹配值。例如假设某个浮点数可表示的匹配值只有1和2,如果将变量赋值为1.4,浮点数的值将为1,1.6为2,1.5为2。像偶数舍入也可以转化为位向量进行理解,例如在1=[0000 0001]与2=[0000 0010]的正中间是[0000 0001.1],它将向2舍入,因为2的最低有效位是偶数0。

当两个浮点数进行运算时,在运算之前他们会分别进行舍入,在运算之后,他们的运算结果将会被进行舍人,由于这种对运算结果的自动舍入,浮点数的运算不具有结合性与分配性,例如a+b+c不一定等于a+(b+c),在第一次运算后a+b与b+c都有可能得出舍入后的值。1e20*(1e20-1e20)(1e20*-1e20)-(1e20*-1e20),前者在第一次运算后会变为,1e20*0,后者是

当一个int变量强制转换为float变量后,它不会溢出,因为float变量可赋值的范围要大于int,但是它有可能被舍入成最近的匹配值,因为int可以精确表示它可被赋值范围内的所有整数,但是float的可表示数值是以M2E的形式分布在数轴上,数值越大,精确度越低。也既是在整数的绝对值超过一个很大的值的时候,它的匹配值无法覆盖整数。

4,同样数值的二进制代码在整数编码和浮点数编码中有什么区别?

例:1234510在无符号编码中的位向量为

1234510=[11000000111001]2

我们先手动将12345的二进制代码转换为IEEE32位浮点数格式。

1,移小数点至最高有效位的右边,左移位数转化为2的幂,[1.1000000111001]213,既是转化成了V=(1)sM2E
2,因为此数为规格化数,根据公式1,M=1+frac,可以舍去最高位的1,变为了[.1000000111001]。
3,添加0使小数位达到23位,[10000001110010000000000]。(32位浮点)
4,构造阶码部分e。E=13,bias=127,E=e-bias,e=E+bias=130。13010=[10001100]2
5,添加符号位,结果为:

1234510=[01000110010000001110010000000000]

转换之后可以看到一个现象,无符号编码删除最高位后的位向量与浮点数小数数位的高位段完全相同。

学习资料:深入理解计算机系统(原书第二版 )—Randal E.Bryant

0 0