我是靠谱客的博主 飘逸玫瑰,最近开发中收集的这篇文章主要介绍如何深刻理解IEEE浮点数的表示(IEEE floating-point representation)舍入问题 (Rounding),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

引言

大家都知道,可以在计算机处理器直接运行的是由0,1构成的机器代码(machine code),本文将介绍浮点数(floating-point number )在机器码中是如何被编码表示的
整数(integer)是如何被编码的呢?小伙伴们应该听过补码,原码,反码吧,这些正是整数被编码的不同规则。

原码:一定字长,在不溢出的情况下,最高位是符号位,跟上该整数二进制表示。符号位中0代表正数,1代表负数。
补码(two's compliment):最高位也是符号位,但是与原码不同的是符号位也参与到求值里。
例如:1001=-2^3+1=-7
而原码中 1001=-1

代表同一数值的原码是可以转换成其补码的。

 很多文章里说补码是无法直接转换成十进制数值,要先换成原码再求,其实这是错误的。理解补码最高位也是参与值的即可。

后续笔者将会撰写一篇文章详细讲解原码,补码,以及反码。

下面开始正题吧!

浮点数(floating-point number)是什么

其实计算机表示小数有两种方式:

  1. 定点数 (fixed-point)
  2. 浮点数(floating-point)
    区别在于,定点数编码小数时小数点位置是确定的,浮点数小数点位置是可以变化的。
    如何用科学计数法来表示二进制小数,即形如:
    V = ( − 1 ) s × M × 2 E V=(-1)^s times M times 2^E V=(1)s×M×2E
    0.25(d)可以写作
    0.01 ( b ) × 2 0 0.01(b)times2^0 0.01(b)×20
    也可以写作
    1.0 ( b ) × 2 − 2 1.0(b)times 2^{-2} 1.0(b)×22
注:括号中的字母
d表示十进制 decimal
b表示二进制 binary
h表示十六进制 hexadecimal

IEEE floating-point representation

正如上文所述,IEEE是编码小数的一种标准。类比一下十进制的科学计数法,实际上也算一种标准,要写成形如
a × 1 0 b ( 其 中 ∣ a ∣ > = 1 且 < 10 ) atimes10^b (其中|a|>=1且<10) a×10ba>=1<10
而二进制和十进制的区别只是基数不同,二进制也可以写成像科学计数法的形式。
而计算机正是用了这种方式

IEEE表示数V,而V可以写成如下形式:
V = ( − 1 ) s × M × 2 E V=(-1)^s times M times 2^E V=(1)s×M×2E
已知数字特点,那么计算机只需要存取s,M,E即可。

s: sign ***占最高的一位***,可以看出是**符号位**,s=1表示负数(或0),s=0表示正数(或0)
M: significand **尾数**,二进制小数
E: exponent 对该数加权(可能是负数)

计算机常见字长有 32bit 64bit,因此IEEE规定了对应的两种不同位数的编码方式:
32位称为单精度
64位称为双精度

这些数就是想把 s,M,E 存起来
最简单的方法就是直接全部转换成对应的二进制数,放到对应的位置上,显然IEEE不是这样。

在这里插入图片描述
如图,图中s编码s,exp编码E,frac编码M。这里的编码规则其实就是IEEE浮点数表示的核心了。

三种情况

设exp位有k位,frac有n位

Case 1(normalized values): exp位不全为0 且 不全为1

规定:
E=exp-Bias
Bias翻译为偏置量 且规定
B i a s = 2 k − 1 − 1 Bias=2^{k-1}-1 Bias=2k11
稍后分析Bias这样规定的原因。

根据位数和exp位的限定,我们可以推测出case1可表示的值范围。

在这里插入图片描述

由此图得知,E的范围比较对称,有一定负数,让浮点数中较小的值也可以编码。

M=1+ frac
由此可见,case1 无法表示0, 因为M永远大于等于1。

Case 2 (denormalized values):
exp位全部0
规定:
E=1-Bias(Bias=2^(k-1)-1)
M=frac

作用:

  1. 表示0 (+0与-0)。
  2. 表示一些非常接近于0的小数。

Case 3(special values):
exp位全部为1

当frac位不全为0时:
表示NaN(not a number) 比如根号下-1

当frac位全为0时:
如:k=3,n=2时
111100 011100 分别表示-∞与+∞

case正负EM
case 1: exp位不全为0或1s=0为正,s=1为负E=exp-BiasM=1+frac
case 2:exp位全部是0s=0为正,s=1为负E=1-BiasM=frac
case 3:exp位全部是1frac=0,s=0表示正无穷,s=1为负无穷;frac!=0,均表示NaNNANA

特点

可以看出一定位数能表示的二进制浮点数是有限的。

k=2,n=2时,让我们列出该情况下可以编码的所有数。
易知,bias=2^1-1=1

为了直观,V都化成了以4为分母的分数。

no.biteEfMV
10 00 0000000
20 00 01001/41/41/4
30 00 10001/21/22/4
40 00 11003/43/43/4
50 01 001001.04/4
60 01 01101/44/55/4
70 01 10101/23/26/4
80 01 11103/47/47/4
90 10 0021018/4
100 10 01211/45/410/4
110 10 10211/23/212/4
120 10 11213/47/414/4
130 11 00----+∞
140 11 01----NaN
160 11 10----NaN
170 11 11----NaN

其中
大家也可以自己列一下这个表,加深理解。

同时我们发现了从case 1到case 2的变化是非常均匀 的,V的变化量为1/16,这正是case2中 规定E=1-bias 的用意!!!
但是注意后面V值变化并不均匀!!!

我们来讲两个例子。

  1. 0 00 10
    可以其判断属于case 2(exp位都是0)
    exp: 00(binary)=0(decimal)
    E=1-bias=1-3=-2
    frac: 0.10(b)=1/4(d)
    M=f= 1/4(d)
    V=2^(0)✖️1/4✖️2 ^(-2)=1/16

  2. 0 10 11
    可以其判断属于case 1(exp位不都是1或者0)
    exp: 10(b)=2(d)
    E=exp-bias=2-3=-1
    frac: 0.11(binary)=3/4(decimal)
    M=1+f=7/4(d)
    V=2^(0)✖️7/4✖️2 ^(-1)=14/16

V与IEEE表示的相互转换

IEEE位格式(bit representation)到V

上文在讲例子时,已经介绍了从位格式求V值。
步骤:

  1. 根据exp位判断属于哪个case
  2. 写出s,exp,frac 根据不同规则求出E,M
  3. 代入公式

V = ( − 1 ) s × M × 2 E V=(-1)^s times M times 2^E V=(1)s×M×2E

V转换成IEEE位格式

步骤:

  1. 明确单精度还是双精度。顺势求出bias值
    单精度: s 1位, exp 8位, frac 13位,bias=127
    双精度: s 1位, exp 11位,frac 52位,bias=1023
  2. 判断是case 1 还是case 2(case3 的情况只有+∞和NaN)
    Bit representation很好看出 exp。
    这种情况也不难,判断一个范围即可,求出case 1能表示的最大值(正数为例)。

单精度:
1 00000000 1111111111111
exp=0
E=1-bias-1-127=-126
frac=0.1111111111111(b)=0.9998779296875
M=0.9998779296875
V=2^(-126)✖️0.999877929687
约等于
1.17535 × 1 0 − 38 1.17535times 10^{-38} 1.17535×1038
若V比此值小,则是case 1。否则是case 2。

双精度
该值约等于
2.22507 × 1 0 − 308 2.22507times 10^{-308} 2.22507×10308

  1. 将V值转换成二进制(只考虑能确切转换成二进制的情况),并化成标准型
    形如
    V = ( − 1 ) s × M × 2 E V=(-1)^s times M times 2^E V=(1)s×M×2E
    注意:
    case 1, 用E来加权,调整M到位数1.xxxxxxx
    case 2, 用E来加权,调整M到位数0.xxxxxxx

举例:
单精度下,V=12345.0(d)
解:显然属于case 1
12345.0(d)=11000000111001
化标准型
V = 2 0 × 1.1000000111001 × 2 13 V=2^{0}times1.1000000111001times 2^{13} V=20×1.1000000111001×213
则 s=0
frac=10000001110010000000000 【13位,少了还得在后面补0,凑成23位】
E=13
exp=E+bias=13+127=140=10001100(b)【恰好8位,少了在前面补0
则位表达为
01000110010000001110010000000000 0 1000110010000001110010000000000 01000110010000001110010000000000

舍入问题 (Rounding)

“Floating-point arithmetic can only approximate real arithmetic, since the representation has limited range and precision. Thus, for a value x, we generally want a systematic method of finding the ‘closest’ value.”

“The IEEE floating-point format defines four different rounding modes. The default method finds a closest match, while the other three can be used for computing upper and lower bounds”

其中说的默认方法是round-to-even,它和传统的四舍五入的唯一区别就是对中值的处理。
四舍五入,顾名思义,五永远是要进位的。
而round-to-even,五的话要round到最近的偶数值。

比如:1.5 四舍五入后 2
1.5 round-to-even 2
2.5 四舍五入后 3
2.5 round-to- even 2

优势:
在统计时,若采用四舍五入,那么数据值总是偏大一些,而round-to-even方法在中值处舍和入的概率都是0.5,数据值较为准确。

mode1.41.61.52.5-1.5
四舍五入1223-2
round-to-even1222-2
round-toward-zero1112-1
round-down1112-2
round-up2223-1

round-toward-zero 模式就是在向0舍入。
round- down就是向数轴负方向舍。
round-up就是向数轴正方向入。

补充:

  1. round-to- even在保留一定位小数时也可以用到。
    比如:1.2350和1.2450保留2位小数。用round-to-even mode后都是1.24
  2. 二进制也可以用round-to-even
    0为even(偶数),1为odd(奇数)
    比如:保留2位小数。
    10.00011 (b)应该为 10.00(b) 而 10.00110(b)应该为10.01(b)。这两个数都不是中值。
    举两个中值(请体会这里中值的含义,是对于保留2位小数而言的)的例子吧!
    10.001(b)应该舍为 10.00(b)
    10.111(b)应该进入为11.00(b)
    注意:都是让小数舍入后最低位为even,即0

二进制小数舍入(Round-to-even)例题:

保留一位小数

before与中值的关系after
10.011大于中值,要入10.1
10.010等于中值,要round-to-even(0)10.0
10.110等于中值,要round-to-even(0)11.0
11.001小于中值,要舍11.0

关于中值:
10.0xx保留一位小数,其中值为10.010,准确的说,10.010是10.0(舍后的值)与10.1(入后的值)的中值。
类比1.5是1(舍后的值)和2(入后的值)的中值。

参考资料:Computer Systems: A Programmer’s Perspective 3rd edition

亲爱的读者们,欢迎指正错误和提问。

最后

以上就是飘逸玫瑰为你收集整理的如何深刻理解IEEE浮点数的表示(IEEE floating-point representation)舍入问题 (Rounding)的全部内容,希望文章能够帮你解决如何深刻理解IEEE浮点数的表示(IEEE floating-point representation)舍入问题 (Rounding)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部