Wed Jan 15 2025
1760 words · 11 minutes

浮点数


Table of Contents

CS:APP Page 75~87

背景:二进制的浮点数,分数 Link to 背景:二进制的浮点数,分数

在计算机中,用二进制的浮点数表示实数 ![](attachments/Pasted image%2020250115201705.png%20) 即 k=jibk×2k\sum_{k=-j}^{i} b_{k} \times 2^k 例如 534=(101.11)25 \frac{3}{4}=(101.11)_{2} 278=(10.111)22 \frac{7}{8} = (10.111)_{2} 1716=(1.0111)21 \frac{7}{16} = (1.0111)_{2}0.11112=12+14+18+116++12n+1.00.1111\dots_{2} = \frac{1}{2}+\frac{1}{4}+\frac{1}{8}+\frac{1}{16}+\dots+\frac{1}{2^{n}}+\dots \to 1.0

有些小数则不能有有限位数表示,例如 13=0.010101[01]2\frac{1}{3} = 0.010101[01]\dots_{2} 15=0.00110011[0011]2\frac{1}{5} = 0.00110011[0011]\dots_{2} 110=0.000110011[0011]2\frac{1}{10} = 0.000110011[0011]\dots_{2} 而在计算机中,存储位数是有限的.所以为了提高精度就需要减小整数部分的位数;为了增加整数部分的位数就需要降低精度.

二进制浮点数的科学计数法 Link to 二进制浮点数的科学计数法

(1)sM2E(-1)^sM\cdot 2^E

  • s是符号位(sign),决定了正负
  • 尾数(significand)的范围是[1.0,2.0)
  • 阶码E(exponent)会以2的E次幂扩大尾数

IEEE浮点数标准 Link to IEEE浮点数标准

精度 Link to 精度

两个IEEE标准:单精度和双精度: ![](attachments/Pasted image%2020250115203736.png%20)

情况1:规格化的值 Link to 情况1:规格化的值

上图中, 当阶码不全为0也不全为1的时候exp ≠ 000…0 并且exp ≠ 111…1

  • 阶码字段exp = E + bias
    • 阶码是unsigned类型
    • 偏移量bias = 2^{k-1} - 1,k是阶码位的位数:
      • 对于单精度是127(exp:1254,E:-126127)
      • 对于双精度是1023(exp:12046,E:-10221023)
  • 尾数的编码隐含了整数部分前导1:M=1.xxxx
    • xxxx就是小数字段frac的比特
    • M=1.0,小数字段是000…0;M=2-ε,小数字段是111…1
    • 这种方法获得了一个额外精度

举例 Link to 举例

  • 以浮点数15213.0为例 float F = 15213.0f; 1521310=111011011011012=1.11011011011012×21315213_{10} = 11101101101101_{2} = 1.1101101101101_{2}\times 2^{13}

  • 过程 M=1.11011011011012M = 1.\underline{1101101101101}_{2} frac=110110110110100000000002frac = \underline{1101101101101} 0000000000_{2} E=13E = 13 Bias=127Bias = 127 Exp=140=100011002Exp = 140 = 10001100_{2}

  • 结果

    01000110011011011011010000000000
    sexpfrac

情况2:非规格化的值 Link to 情况2:非规格化的值

当阶码域exp全为0(exp = 000…0)时,所表示的数是非规格化形式

  • 阶码的值E=1-Bias而不是-Bias
  • 尾数的编码隐含了整数部分前导0:M=0.xxxx
    • xxxx就是小数字段frac的比特
  • exp = 000…0,frac = 000…0
    • 表示0
    • 对于+1和-1的符号位有+0.0和-0.0
  • exp = 000…0,frac ≠ 000…0
    • 表示非常接近于0的数
    • 分布均匀地接近于0.0

情况3:特殊值 Link to 情况3:特殊值

当阶码域exp全为1(exp=111…1)的时候

  • frac=000…0

    • 表示无穷∞(Infinity)
    • 能够表示溢出的结果
    • 当s=0时是+∞;当s=-1时是-∞
  • frac≠000…0

    • 表示不是一个数(NaN)
    • 能够表示运算结果不是实数或无穷,例如sqrt(-1),∞-∞,∞*0

在数轴上的分布 Link to 在数轴上的分布

![](attachments/Pasted image%2020250115235636.png%20) 规格化的值不是均匀分布的;非规格化的值聚集在0附近,并且是均匀分布的.

数字示例:以8位浮点格式为例 Link to 数字示例:以8位浮点格式为例

sexpfrac
1-bit4-bit3-bit
偏移量 Bias = 2^ (4-1) = 7
![](attachments/Pasted image%2020250116000313.png%20)
完整范围:
在-1.0~1.0附近:

浮点运算 Link to 浮点运算

舍入(Round) Link to 舍入(Round)

基本思想 Link to 基本思想

首先计算精确值,然后按需要的精度舍入

舍入方式 Link to 舍入方式

  • 向0四舍五入
  • 向下(-∞)四舍五入
  • 向上(+∞)四舍五入
  • 四舍五入偶成双 这是默认方式.即大于中间数(在十进制下是5,在二进制下是1)的向上入,小于中间数的向下舍,等于中间数的向偶数舍入. 对于十进制: Round(7.8949999,2)=7.89Rou nd(7.8949999,2) = 7.89 Round(7.8950001,2)=7.90Rou nd(7.8950001,2) = 7.90 Round(7.8950000,2)=7.90Rou nd(7.8950000,2) = 7.90 Round(7.8850000,2)=7.88Rou nd(7.8850000,2) = 7.88 对于二进制也类似: Round(10.00 011,2)=10.00Rou nd(10.00\ 011,2) = 10.00 Round(10.00 110,2)=10.01Rou nd(10.00\ 110,2) = 10.01 Round(10.11 100,2)=11.00Rou nd(10.11\ 100,2) = 11.00 Round(10.10 100,2)=10.10Rou nd(10.10\ 100,2) = 10.10

加法(addtion) Link to 加法(addtion)

(1)s1M12E1+(1)s2M22E2(-1)^{s_{1}} M_{1} 2^{E_{1}} + (-1)^{s_{2}} M_{2} 2^{E_{2}} 假设E1>E2 精确结果为 (1)sM 2E(-1)^{s} M\ 2^{E} 其中:

  • 符号s由对齐后的符号决定.
  • 尾数M对齐后相加的结果
  • 指数E是E1 调整:
  • 如果M>=2,右移M,然后E增加1
  • 如果M<1,左移k位,E减小k
  • 如果E溢出,溢出为无穷
  • 舍入M使得符合frac位精度要求

对齐那样的处理方法导致了一个特性,就是不符合加法结合律: (3.14+1e10)-1e10 = 0, 3.14+(1e10-1e10) = 3.14 符合加法交换律

乘法(multiplication) Link to 乘法(multiplication)

(1)s1M12E1×(1)s2M22E2(-1)^{s_{1}} M_{1} 2^{E_{1}} \times (-1)^{s_{2}} M_{2} 2^{E_{2}} 精确结果为 (1)sM 2E(-1)^{s} M\ 2^{E} 其中:

  • 符号位s: s1^ s2
  • 尾数M:M1×M2
  • 指数E:E1+E2 调整:
  • 如果M>=2,右移M,然后E增加1
  • 如果E溢出,溢出为无穷
  • 舍入M使得符合frac位精度要求 类似于浮点数加法的特性,浮点数乘法可能不符合乘法结合律和乘法分配律 (1e20*1e20)*1e-20 = inf, 1e20*(1e20*1e-20) = 1e20 1e20*(1e20-1e20) = 0.0, 1e20*1e20-1e20*1e20 = NaN 不过,在大多数情况下,只要差距不是这么悬殊,不对inf和NaN实数运算,数学规律都是适用的. 可以保证对于 ab  &  c0acbca\geq b \;\& \; c\geq 0 \Rightarrow a*c\geq b*c ab  &  c0acbca\geq b \;\& \; c\leq 0 \Rightarrow a*c\leq b*c aNaNaa0a\ne NaN \Rightarrow a*a \geq 0

C语言中的浮点数 Link to C语言中的浮点数

C语言提供了两种不同的浮点数:单精度float和双精度double 在int,float,double类型之间进行强制类型转换时.原则如下: 与signed和unsigned类型相互转换不会改变比特位不同的是,这里比特会发生实质性的改变

  • double/float -> int

    • 直接截去小数部分
    • 向0舍入
    • 超过int范围或转换NaN时是未定义行为:通常置为TMin
  • int/float -> double 因为double有更大的范围,也有更大的精度,所以能够保证是精确值

  • int -> float 数字不会溢出,但是可能被舍入

  • double ->float

    • 因为float范围更小,所以可能溢出为+∞或-∞;因为精度更小,所以可能被舍入

浮点数的范围 Link to 浮点数的范围

补充一下浮点数能够表示的范围

  • 单精度浮点数
格式最小值最大值
规格化21262^ {-126}2127×(2223)3.4×10382^{127} ×(2-2^ {-23})\approx 3.4\times 10^{38}
非规格化223×2126=21491.4×10452^ {-23}\times 2^{-126}=2^{-149}\approx 1.4 \times 10^{-45}2126×(1223)1.18×10382^ {-126} ×(1-2^ {-23}) \approx 1.18\times_{1}0^{-38}
  • 双精度浮点数
格式最小值最大值
规格化210222^ {-1022}21023×(2252)1.8×103082^{1023} ×(2-2^ {-52})\approx 1.8\times 10^{308}
非规格化252×21022=210744.9×103242^ {-52}\times 2^{-1022}=2^{-1074} \approx 4.9\times 10^{-324}2126×(1223)2.2×103082^ {-126} ×(1-2^ {-23})\approx 2.2\times 10^{-308}
Thanks for reading!

浮点数

Wed Jan 15 2025
1760 words · 11 minutes

© Tan Kimzeg | CC BY-SA 4.0