CS61C FALL 2023 浮点数表示&IEEE 754 Floating Point Standard

前言

此文章仅用于记录个人学习cs61c过程中对课程内容的理解,如果你在学习过程中遇到了困难可以参考参考,但是本文并不能充当原课程的替代品

由于水平有限/语文功底不行,文章可能存在诸多谬误,欢迎指正

另外,因为一些原因(懒/学过),稿主省略了部分内容

不推荐单纯的收藏/粘贴复制到笔记中,个人看来这样学习是效率最低的

浮点数

计算机可以利用n位表示2^n种事物,但对于非常大/小的数字又该怎么表示?如何表示浮点数?

先固定小数点位置试试

10.101 0 2 = 1 × 2 1 + 1 × 2 − 1 + 1 × 2 − 3 = 2.62 5 10 10.1010_2 = 1\times2^1 + 1\times2^{-1} + 1\times2^{-3} = 2.625_{10} 10.10102=1×21+1×21+1×23=2.62510

如果我们固定二进制数小数点的位置如上,那么一个六位的二进制数的表示范围为:0 to 3.9375

加法&乘法

规则照搬十进制的加法和乘法即可:

1. 5 10 + 0. 5 10 = 2. 0 10 1.5_{10}+0.5_{10}=2.0_{10} 1.510+0.510=2.010 也即 01.10 0 2 + 00.10 0 2 = 10.00 0 2 01.100_2+00.100_2=10.000_2 01.1002+00.1002=10.0002

1. 5 10 × 0. 5 10 = 0.7 5 10 1.5_{10}\times0.5_{10}=0.75_{10} 1.510×0.510=0.7510 也即 01.10 0 2 × 00.10 0 2 = 0000.11000 0 2 01.100_2\times00.100_2=0000.110000_2 01.1002×00.1002=0000.1100002

“浮点”数

为什么不固定小数点位置?——最有效地利用内存、精度更高…

对于 0.1640625 0.1640625 0.1640625 也即 . . . 00000.001010100000... ...00000.001010100000... ...00000.001010100000... 我们只需要传输10101和一个表示其浮点位置的参数即可——前后多余的零都不需要考虑

二进制数的科学计数法

规范化形式为 1. x x x x 2 × 2 y y y y y y 1.xxxx_2 \times 2^{yyyyyy} 1.xxxx2×2yyyyyy,利用指数来变更小数点的位置

浮点数表示

我们总可以把浮点数表示为上述科学计数法的形式

则一个32bit的浮点数的存储形式为:

符号(±)指数部分(y)小数部分/定点数(x)
1 bit8 bits23 bits

——我们事实上并不存储1.xxx的1,因为他永远是1

指数部分采用补码的表示方式

其表示的正数范围为: 1.2 × 1 0 − 38 1.2 \times 10^{-38} 1.2×1038 ~ 3.4 × 1 0 38 3.4 \times 10^{38} 3.4×1038

Overflow/Underflow

正负溢出,正负下溢

如何解决?更多的bit

IEEE 754 Floating Point Standard

基本内容

表示方法

1bit符号位(1负0正),8bits指数位,23bits小数位

指数

0无前导1,规定:全0表示0–0不唯一?bias notation

尾数/小数部分

省略了二进制科学计数法中的前导1,小数部分永远小于1大于0

bias notation

比较浮点数的时候我们不希望单独设计比较浮点数的电路,但是我们当前的表示方法下会出现这样的滑稽结果:

  • 1/2>2,即0 1111 1111 000… 大于 0 0000 0001 000…
  • 我们希望比较指数的时候,较为直接:小的数字二进制小,大的数字二进制大(无符号整数?)
  • 怎么办?加个偏差bias
数字原码bias 127 <无符号>
-1281000 00001111 1111<保留作别的用途>
-1271000 00010000 0000<保留作别的用途>
-1261000 00100000 0001
1270111 11111111 1110

真实的表示范围为-126~127,则计算一个数的公式为:

  • ( − 1 ) s i g n × ( 1 + S i g n i f i c a n d ) × 2 E x p o n e n t − 127 (-1)^{sign} \times (1 + Significand) \times 2^{Exponent-127} (1)sign×(1+Significand)×2Exponent127

如此,既不会出现±0的情况,也不会出现类似于1/2 < 2的情况

special numbers

正无穷负无穷?用最大的来表示:1111 1111

  • 当然,尾数部分为全0:因为127.9999…再往上,自然是128.00000…

我们现在都得到了什么?

指数尾数表示对象
000
0非零???
1-254xxxx±浮点数
2550±无穷
255非零???
NaN

计算中会有很多错误,如:0/0,sqrt(-4),即NaN,有 2 23 − 1 2^{23}-1 2231 种可以被定义为NaN的类型——可以编码特定的错误类型,具体编码方式取决于硬件

任何和NaN进行的操作结果均为NaN——这意味着我们可以进行错误的传递

不均匀的浮点数&规范化导致的问题

规范化后,最小的正浮点数是多少?
a = 1.000.. 0 2 × 2 − 126 = 2 − 126 a=1.000..0_2 \times 2^{-126}=2^{-126} a=1.000..02×2126=2126

第二小的?
b = 1.0000...0 1 2 × 2 − 126 = 2 − 126 + 2 − 149 b= 1.0000...01_2 \times 2^{-126}=2^{-126} + 2^{-149} b=1.0000...012×2126=2126+2149

之后的每个数的间隔均为 2 − 149 2^{-149} 2149,但0和最小的数之间却有道天堑

这是我们的前导1导致的问题,怎么办?

——Denorms

Denorms

—— 此处就可以用指数0,尾数非0的部分了

将前导1分解为2^23个均匀分布的数:

尾数有 2 23 − 1 2^{23}-1 2231 个,无隐含前导1,隐含指数-126

最小的? 0.0000...0 1 2 × 2 − 126 = 2 − 149 0.0000...01_2\times2^{-126}=2^{-149} 0.0000...012×2126=2149

最大的? 0.1111...1 1 2 × 2 − 126 = ( 1 − 2 − 23 ) × 2 − 149 = 2 − 126 − 2 − 149 0.1111...11_2\times2^{-126}=(1-2^{-23})\times2^{-149}=2^{-126}-2^{-149} 0.1111...112×2126=(1223)×2149=21262149

此处的最小间隔也为 2 − 149 2^{-149} 2149 且最终也可以跨度到规范化的数字

总结
指数尾数表示对象
000
0非零Denorms
1-254xxxx±浮点数
2550±无穷
255非零NaN

例子:1/3

由于 ∑ k = 1 ∞ 1 4 k = 1 3 \sum_{k=1}^{\infty}{\frac{1}{4^k}}=\frac{1}{3} k=14k1=31 ,即 0.01010101.. . 2 = 0.3333.. . 10 0.01010101..._2=0.3333..._{10} 0.01010101...2=0.3333...10,存储为0 01111101 010101…010

其他问题

不均匀精度

——因为总的来看,它的精度是不均匀的

0 ~ 2 − 125 2^{-125} 2125的精度为 2 − 149 2^{-149} 2149, 2 − 125 2^{-125} 2125 ~ 2 − 124 2^{-124} 2124的精度为 2 − 148 2^{-148} 2148 2 0 2^{0} 20 ~ 2 1 2^{1} 21的精度为 2 − 23 2^{-23} 223 2 23 2^{23} 223 ~ 2 24 2^{24} 224的精度为 2 0 2^{0} 20——我们在将其指数等分为 2 23 2^{23} 223

一个数字不可能同时很大,又有很小的精度——这就意味着很大的数在与小于其精度的数相加时,没有足够的bit,会丢失这个数:

– 1.5 × 1038 + ( 1.5 × 1 0 38 + 1.0 ) = 0.0 –1.5\times10{38} + (1.5\times10^{38} + 1.0)=0.0 –1.5×1038+(1.5×1038+1.0)=0.0

( – 1.5 × 1038 + 1.5 × 1 0 38 ) + 1.0 = 1.0 (–1.5\times10{38} + 1.5\times10^{38} )+ 1.0=1.0 (–1.5×1038+1.5×1038)+1.0=1.0

rounding
四舍五入

首先有个“有效位数”,假定为4

  • 1.001 011 舍入结果为1.001
  • 1.001 101 舍入结果为1.010
  • 距离相等咋办?
    • 1.001 100 舍入结果为1.010
    • 1.000 100 舍入结果为1.001

如此,我们便得到均等机会的四舍五入

其他

永远向上/下/0舍入

0.1+0.2=0.3000000…04

精度问题嘛,0.1

浮点数加法

更加复杂:破坏规范化以匹配指数–相加尾数–得到一个共同的指数–规范化

转换&int

float to int:截断尾数

int to float:转换为最近的浮点数

int to float to int:gap够大(精度不够用了)时和原来的数不相等!双精度?双精度也不能解决这个问题,这个问题不可能解决——总存在这么一个数

其他精度

单精度:binary32/fp32

双精度:binary64

思想与单精度一样,更高的精度:1bit符号,11bits指数,52bits尾数,共64bits

表示范围:2.0 x 10-308 to almost as large as 2.0 x 10308(我懒得用latex语法了,将就着看吧)

binary128、256…
binary16/fp16

1/5/10

bfloat16

1/8/7——faster machine learning

U-bit!!!

指数位数、尾数尾数随意变…具体怎么设计的…请感兴趣的读者查阅更加深入的资料

——尚未被所有硬件支持

后记

稿主开始学习这部分内容的时候没想过要花这么长的时间…学到最后身心俱疲

看书看不懂,看ppt看不懂,听网课查资料又花了好久…毁灭吧,累了

再吐槽一句…csdn的md编辑器真难用,我从typora直接复制粘贴过来还得修修补补一些地方…csdn的文章标签也好难用,每次分享个笔记都要想想什么标签比较合适,不满3级不能自定义标签,现存的好多标签都没有…

总之,完结撒花~,欢迎大家交流

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值