浮点数编码详解

本文详细介绍了浮点数在计算机中的表示方式,基于科学计数法,通过尾数和指数来存储。讲解了32位浮点数的存储模型,包括阶码和尾数的表示,探讨了浮点数表示的范围和精度。还提到了浮点数的不均匀性和稀疏性,并阐述了IEEE 754标准对于浮点数规范化的规定,包括单精度和双精度浮点数的存储细节,以及特殊值如0、无穷和NaN的表示。

  浮点数的表示思想是基于科学计数法的。例如:1234.5用科学计数法可表示为 1.2345 × 1 0 3 1.2345 \times 10^3 1.2345×103,其中1.2345称为尾数(mantissa),3称为指数或阶(exponent),10称为基数(radix)。在已知进制的情况下,只需要记录尾数和指数即可表示这个浮点数。

  同理,在计算机中浮点数表示以2为基数,只需记录尾数和指数即可。例如: 33.25 = ( 100001.01 ) 2 × 2 0 = ( 0.10000101 ) 2 × 2 6 33.25=(100001.01)_2 \times 2^0 =(0.10000101)_2 \times 2^{6} 33.25=(100001.01)2×20=(0.10000101)2×26,在计算机中,只需要记录0.10000101和6即可。

  为了在计算机中表示一个浮点数,我们需要表示其尾数和指数。指数使用阶码(移码)来表示,尾数表达均以0.1开头,因此只存储0.1后的数字,这样可以增加表示的范围。例如在32位浮点数中,用8位移码(bias= 2 8 − 1 = 128 2^{8-1}=128 281=128)表示指数,则 33.25 = ( 0.10000101 ) 2 × 2 6 33.25 = (0.10000101)_{2} \times 2^{6} 33.25=(0.10000101)2×26中指数可存储为 6 + 128 = 134 = ( 10000110 ) 2 6+128=134=(10000110)_2 6+128=134=(10000110)2,的尾数部分存储为 ( 00001010000000000000000 ) 2 (00001010000000000000000)_2 (00001010000000000000000)2

0(符号位)1~8(阶)9~31(尾数)
01000011000001010000000000000000

  上述存储模型中移码范围 [ ( 00000000 ) 2 , ( 11111111 ) 2 ] [(00000000)_2,(11111111)_2] [(00000000)2,(11111111)2],实际表示范围为[-128,127]。尾数的表示范围 [ ( 0.10...0 ) 2 , ( 0.11...1 ) 2 ] [(0.10...0)_2,(0.11...1)_2] [(0.10...0)2,(0.11...1)2],即 [ 2 − 1 , 2 0 − 2 − 24 ] [2^{-1},2^0-2^{-24}] [21,20224]。所以该模型能表达的最大正数0.11…1 × 2 11...1 = ( 1 − 2 − 24 ) × 2 127 \times 2^{11...1}=(1-2^{-24}) \times 2^{127} ×211...1=(1224)×2127,最小正数0.10…0 × 2 00...0 = 1 2 × 2 − 128 = 2 − 129 \times 2^{00...0}=\frac{1}{2} \times 2^{-128}=2^{-129} ×200...0=21×2128=2129

  浮点数的范围比定点数的范围大,但是同样位数能编码的数个数相同,因此浮点数表达的数之间稀疏且不均匀。阶数决定了浮点数的表达范围,尾数决定了浮点数的而表达精度。

  以32位浮点数为例,在 [ 2 1 , 2 2 ] [2^{1},2^{2}] [21,22] [ 2 2 , 2 3 ] [2^{2},2^{3}] [22,23]之间数的个数相同,都为 2 23 2^{23} 223个(由尾数的可能情况确定),但是两者的区间长度分别为2和4,所以数字在 [ 2 1 , 2 2 ] [2^{1},2^{2}] [21,22]的分步比在 [ 2 2 , 2 3 ] [2^{2},2^{3}] [22,23]的分步密集。推广可知:越靠近上溢区,数字分步越稀疏。

  浮点数表达个数有限,部分实数可以编码表示,其他不能编码表示的实数则用最近的可表达数来代替表示。例如:

#include <iostream>
using namespace std;

int main()
{
	float num;
	cout.setf(ios::fixed,ios::floatfield);
	while(1)
	{
		cout<<"input:";
		cin>>num;
		cout<<num<<endl;
	}
	return 0;
}

运行结果如下:

input:61.419997
61.419998
input:61.419998
61.419998
input:61.419999
61.419998
input:61.42
61.419998
input:61.420001
61.420002

  由于61.419998和61.420002是两个可表达数,当输入的数据是一个不可表达数时,机器将其转化为最邻近的可表达数。


  但是同一个数可以用多种形式表达,例如 33.25 = ( 0.10000101 ) 2 × 2 6 = ( 1.0000101 ) 2 × 2 5 = ⋅ ⋅ ⋅ 33.25 = (0.10000101)_2 \times 2^6 = (1.0000101)_2 \times 2^5=··· 33.25=(0.10000101)2×26=(1.0000101)2×25=这样不利于数据的传输和程序的移植,因此出现了IEEE 754标准。IEEE 754规定的规格化数形如:+/- ( 1. X X X X X X X ) 2 × 2 E (1.XXXXXXX)_2 \times 2^{E} (1.XXXXXXX)2×2E,其中尾数的1可不存储。IEEE 754规定了单精度浮点数(32 bit)和双精度浮点数(64 bit):

  1.单精度浮点数

  • 存储模型
SExponentSignificand
01~89~31
1 bit8 bit23 bit
  • [ ( 00000001 ) 2 , ( 11111110 ) 2 ] [(00000001)_2,(11111110)_2] [(00000001)2,(11111110)2]即[-126,127];bias=127
  • 尾数 最高位总为1,可以隐含表示。存储23位,可表示24位的定点小数。
  • 真值: ( − 1 ) S × ( 1 + S i g n i f i c a n d ) × 2 E x p o n e n t − 127 (-1)^{S} \times (1+Significand) \times 2^{Exponent-127} (1)S×(1+Significand)×2Exponent127
  • 规格化数表达范围:

  最小正数: ( 1.00...00 ) 2 × 2 00..01 = 2 − 126 (1.00...00)_2 \times 2^{00..01}=2^{-126} (1.00...00)2×200..01=2126

  最大正数: ( 1.11...1 ) 2 × 2 11...10 = ( 2 − 2 − 23 ) × 2 127 = ( 1 − 2 − 24 ) × 2 128 (1.11...1)_2 \times 2^{11...10}=(2-2^{-23}) \times 2^{127}=(1-2^{-24}) \times 2^{128} (1.11...1)2×211...10=(2223)×2127=(1224)×2128

  因此,规范化数的表达范围 [ − ( 1 − 2 − 24 ) × 2 128 , − 2 − 126 ] ∪ [ 2 − 126 , ( 1 − 2 − 24 ) × 2 128 ] [-(1-2^{-24}) \times 2^{128},-2^{-126}]\cup[2^{-126},(1-2^{-24}) \times 2^{128}] [(1224)×2128,2126][2126,(1224)×2128]


例1: 已知float型变量x的机器数为0xBEE00000,求x的值。

0xBEE00000= ( 1011   1110   1110   0000   0000   0000   0000   0000 ) 2 (1011 \ 1110 \ 1110 \ 0000 \ 0000 \ 0000 \ 0000 \ 0000)_2 (1011 1110 1110 0000 0000 0000 0000 0000)2

101111101(125)11000000000000000000000

真值为 ( − 1 ) 1 × ( 1 + 2 − 1 + 2 − 2 ) × 2 − 2 = − 1.75 × 2 − 2 = − 0.4375 (-1)^1 \times (1+2^{-1}+2^{-2}) \times 2^{-2}=-1.75 \times 2^{-2}=-0.4375 (1)1×(1+21+22)×22=1.75×22=0.4375

步骤:

  • 1.在二进制表达式中提取表达阶和尾数的部分;
  • 2.利用公式分别求出阶和尾数的十进制数;

例2: 已知float型变量x的值为-12.75,求x的机器数。

− 12.75 = − 1100.11 B = − 1.10011 B × 2 3 -12.75=-1100.11B=-1.10011B \times 2^{3} 12.75=1100.11B=1.10011B×23

E = 3 + 127 = 130 = ( 10000010 ) 2 E=3+127=130=(10000010)_2 E=3+127=130=(10000010)2

尾数 S i g n i f i c a n d = ( 100110...0 ) 2 Significand=(100110...0)_2 Significand=(100110...0)2

11000001010011000000000000000000

所以机器数为11000001010011000000000000000000

步骤:

  • 1.写出浮点数的二进制表达式;
  • 2.转化为规格化形式;
  • 3.分别求出阶和尾数的表示;

  2.双精度浮点数

  • 存储模型
SExponentSignificand
01~1112~63
1 bit11 bit52 bit
  • [ ( 00000000001 ) 2 , ( 11111111110 ) 2 ] [(00000000001)_2,(11111111110)_2] [(00000000001)2,(11111111110)2]即[-1022,1023];bias=1023
  • 尾数 最高位总为1,可以隐含表示。存储52位,可表示53位的定点小数。
  • 真值: ( − 1 ) S × ( 1 + S i g n i f i c a n d ) × 2 E x p o n e n t − 1023 (-1)^{S} \times (1+Significand) \times 2^{Exponent-1023} (1)S×(1+Significand)×2Exponent1023
  • 规格化数表达范围:

  最小正数: ( 1.00...00 ) 2 × 2 00..01 = 2 − 1022 (1.00...00)_2 \times 2^{00..01}=2^{-1022} (1.00...00)2×200..01=21022

  最大正数: ( 1.11...1 ) 2 × 2 11...10 = ( 2 − 2 − 52 ) × 2 1023 = ( 1 − 2 − 53 ) × 2 1024 (1.11...1)_2 \times 2^{11...10}=(2-2^{-52}) \times 2^{1023}=(1-2^{-53}) \times 2^{1024} (1.11...1)2×211...10=(2252)×21023=(1253)×21024

  因此,规格化数的表达范围 [ − ( 1 − 2 − 53 ) × 2 1024 , − 2 − 1022 ] ∪ [ 2 − 1022 , ( 1 − 2 − 53 ) × 2 1024 ] [-(1-2^{-53}) \times 2^{1024},-2^{-1022}]\cup[2^{-1022},(1-2^{-53}) \times 2^{1024}] [(1253)×21024,21022][21022,(1253)×21024]

  除上述的规格化数外,浮点数还可以表示一些特殊的约定值及非规格化数。

以float型为例:

SignedExponentSignificandValue
X00+/- 0
X0nonzeroDenorms
X1-254XX...XNorms
X2550+/- Infinity
X255nonzeroNaN
  • 0的表示:阶和尾数全为0时表示真值0.

  +0: 0   00000000   00000000000000000000000 0 \ 00000000 \ 00000000000000000000000 0 00000000 00000000000000000000000

  -0: 1   00000000   00000000000000000000000 1 \ 00000000 \ 00000000000000000000000 1 00000000 00000000000000000000000

  • + / − ∞ +/- \infty +/的表示:阶全为1,尾数全为0

   + ∞ : 0   11111111   00000000000000000000000 + \infty : 0 \ 11111111 \ 00000000000000000000000 +:0 11111111 00000000000000000000000

   − ∞ : 1   11111111   00000000000000000000000 -\infty : 1 \ 11111111 \ 00000000000000000000000 :1 11111111 00000000000000000000000

  例如: 1.0 0 = + ∞ \frac{1.0}{0}=+\infty 01.0=+   − 1.0 0 = − ∞ \frac{-1.0}{0}=-\infty 01.0=   1 + ( + ∞ ) = + ∞ 1+(+\infty)=+\infty 1+(+)=+   1 + ( − ∞ ) = − ∞ 1+(-\infty)=-\infty 1+()=   + ∞ + ( + ∞ ) = + ∞ +\infty+(+\infty)=+\infty ++(+)=+   − ∞ − ( + ∞ ) = − ∞ -\infty-(+\infty)=-\infty (+)=

  • NaN(Not a Number)的表示:阶全为1,尾数不全为0

  例如: − 4.0 = N a N \sqrt{-4.0}=NaN 4.0 =NaN   0 0 = N a N \frac{0}{0}=NaN 00=NaN   ∞ ∞ = N a N \frac{\infty}{\infty}=NaN =NaN   + ∞ − ( + ∞ ) = N a N +\infty-(+\infty)=NaN +(+)=NaN   + ∞ + ( − ∞ ) = N a N +\infty+(-\infty)=NaN ++()=NaN

  • 非规格化数(Denorms)的表示:阶全为0,尾数不全为0

  形式: ( − 1 ) S × 0. X X . . . X × 2 − 126 (-1)^{S} \times 0.XX...X \times 2^{-126} (1)S×0.XX...X×2126

  范围: [ − ( 1 − 2 − 23 ) × 2 − 126 , 0 ) ∪ ( 0 , ( 1 − 2 − 23 ) × 2 − 126 ] [-(1-2^{-23})\times 2^{-126},0)\cup(0,(1-2^{-23})\times 2^{-126}] [(1223)×2126,0)(0,(1223)×2126] 位于下溢区。

更多内容欢迎参观我的个人站

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值