浮点数运算案例

浮点数运算案例


前面有写过一篇面试题博文 0.1+0.2 是否等于 0.3。里面也涉及到浮点数运算。本文来详细列举一个浮点数运算案例。

浮点数运算五个步骤

1. 对阶
原则是小阶对大阶。
如 0.000101 的科学记数法为 1.012^-4 。
而 0.0101 的科学记数法为 1.01
2^-2 。
小阶就是 -4,大阶就是 -2。
这里需要把 -4 调整成 -2。则 0.000101 的科学记数法为 0.0101 2^-2 。
阶数相同了,就可以进行尾数运算。
那么为什么不用大阶对小阶昵。如果把 0.0101 的科学记数法调整为 1.0
2^-4。这样就是高位移出。损失的精度更高。

2. 尾数运算
对阶完之后,就可以将尾数进行运算了。

3. 规格化
规格化指的是对于 IEEE754 标准的浮点数来说,尾数必须是1.M的形式。
规格化操作分为左规和右规两种情况。
左规指的就是小数点往左移动,比如 0.000101 变成 1.012^-4。
右规指的就是小数点往右移动,比如10.001 变成 1.001
2^1。右规一般只移动一位,发生在进位的情况下。比如二进制 11+1 = 100。

4. 舍入处理
舍入其实就是四舍五入。溢出的数为 0 则直接舍去,为 1 则加1。
比如二进制 011110011 只要保留 8 位。因为最后一位尾数是1,则 01111001+1= 01111010。而 二进制 011110010 如果保留 8 位。最后一位尾数是0,直接舍去。结果为 01111001。

5. 溢出判断
溢出判断指阶码值是否产生溢出。
若阶码值超过了阶码所能表示的最大正数,则为上溢。若此时浮点数为正数,则为正上溢,记为+∞,若浮点数为负数,则为负上溢,记为-∞。
比如用 8 位表示阶码值。则范围为 2^8-1=255。要考虑负数的情况下,范围为 -127-127,此时的阶码值如果是 128。就是上溢。

若阶码值超过了阶码所能表示的最小负数,则为下溢,若此时浮点数为正数,则为正下溢,若浮点数为负数,则为负下溢。正下溢和负下溢都作为0处理。
同样如果用 8 位表示阶码值。存在负数的情况下,范围为 -127-127。而此时的阶码值如果是-128。就是下溢。

案例

下面我们来计算一下 0.3+1.6 = 1.9000000000000001。

将 0.3 转换二进制。浮点数转二进制是乘2取整数部分。

0.3*2=0.6
0.6*2=1.2
0.2*2=0.4
0.4*2=0.8
0.8*2=1.6
0.6*2=1.2(从这里开始循环1001)

结果为 0.0100110011001100(1001)…(1001部分无限循环)
规格化为:1.001100110011… * 2^-2

将 1.6 转换二进制。浮点数转二进制是乘2取整数部分。

0.6*2=1.2
0.2*2=0.4
0.4*2=0.8
0.8*2=1.6
0.6*2=1.2(从这里开始循环1001)

结果为 1.1001100110011001(1)…(0011部分无限循环)
规格化为:1.100110011001… * 2^0

1. 对阶
0.3 的阶数为 -2,1.1 的阶数为0。所以把 0.3 还原为 0.01001100 * 2^0。

2. 尾数相加
因为 64 位表示二进制需要四舍五入。
所以 0.3 的二进制需要进一位。
0. 0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100(1)
结果为
0. 0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1101

同理1.6 的二进制也需要进一位。
1.1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001(1)
结果为
1.1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010

相加:
0. 0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1101
+1.1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010
1.1110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0111

3. 格式化
格式化指的就是1*M的形式,这里已经是格式化的数据了。

4. 舍入处理
由于 0.3 二进制小数点右移了2位。且第一位为1。所以需要进1。
结果为
1.1110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 1110

5.溢出判断
由于没有溢出,这里不需要做溢出判断。

所以最后的结果用 64 位表示为:
因为是正数,所以首位用 0 表示。
整数部分为 2^(11-1)-1+(-2)=1021。用二进制表示为 01111111101
小数部分为 1110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 1110
所以(0.3)+(1.6)=
0 01111111101 1110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 1110
转换为10进制为:1.9000000000000001

发布了280 篇原创文章 · 获赞 2497 · 访问量 20万+

猜你喜欢

转载自blog.csdn.net/weixin_44135121/article/details/105219908
今日推荐