Post

Float_points

g– title: Float Points date: 2025-3-5 17:30:00 +0800 categories: [cs61c, Float Points] tags: [notebook] description: 介绍浮点数设计的原理 pin: false —

对于通常的32bits存储数据而言,有$2^{32}-1$个数可以存储,而不能做到涵盖更大的数字或者是小数,这就是浮点数存在要解决的问题

想到科学计数法,有一个尾数和一个指数作为信息传递,所以可以应用到浮点数上

IEEE754标准规定浮点数由

3130-2322-0
SExponentSignificand
1 bit8 bits23 bits

但是这个范围有可能还是不够用,那么可以上双精度浮点数double

6362-5251-0
SExponentSignificand
1 bit11 bits52 bits

现在给出计算实际值的浮点数转换方式,这里对指数位设置了偏差(bias),这样就可以把指数位当作无符号数处理完减去偏差简化计算 \((-1)^S * (1 + Significand) * 2^{Exponent-127}\) 这是float的计算方式,如果是double的话就是以1023作为偏差

现在还有一些特殊值,如0、正负无穷等,现在来介绍这些特殊值

我们知道如果只是这样简单的设定,那么浮点数是不能涵盖很多数的,那么就会对这些特殊值有特殊的表示,总览大致如下

ExponentSignificandObject
000
0nonzeroDenorm
1-254anything+/- fp
2550+/- $\infty$
255nonzeroNaN

我们把一般的能直观表示的数称为规格数,即上表中的+/- fp,但显然这样的数字无法包括极小的值到0之间的间隔以及0,且面对溢出的情况无法表示,所以设置非规格数表示0以及0两边的间隔,用特殊数表示NaN以及无穷,而平常所说的数据范围一般是基于规格数而言的范围,即

\[0\ \ 00000001\ \ 0000000000000...0 \\ \sim\\ 0\ \ 11111110\ \ 1111111111111...1\]

化为十进制即为

\[[-3.4*10^{38}, -1.18*10^{-38}]∪[1.18*10^{-38}, 3.4*10^{38}]\]

现在来详细说说非规格数存在的意义

非规格数存在的意义主要是为了解决突兀的间隔,即从0到最小规格数的间隔,取最小规格数来看是$2^{-126}$,那么若在不突兀的角度来看是什么样呢?恰如1的下一个数应该是2,这个最小规格数的下一位是$2^{-126}+2^{-149}$,这不合理,而造成这样现象的原因在于我们在规格数中存的尾数是默认加上1的,这就导致了这样的不连续性,所以我们将对其去规格化称为非规格数,即换一种算法进行计算实际值,即不默认加1,这时候非规格数的最小值就是$2^{-149}$,而显然它的下一个是$2^{-148}$,确实是最小非规格数的两倍,有连续性。

如果接着这个往后拓展,就是随着指数位的增加,有效值位的增加带来的实际值增加的“步幅”会每次乘2

在最后跨越规格数的最大值就来到了无穷,再往后就是很多的表示NaN的数,这就是浮点数表示的规则

关于浮点数的四舍五入: 跟传统的四舍五入有细微不同,浮点数的四舍五入不是单纯的处于中间值如2.5的时候就直接进一,而是向偶数舍入,即$2.5->3$且$3.5->4$

最后需要注意的是浮点数因为终究不能精确地表示所有的数据,所以有很多数据只是近似,而这种近似在做加减的时候很可能有截断误差,如一个极大的数加1有可能就会吞掉这个小数,所以有些说法问浮点数的加减是否具有结合性?那么就是错误的,因为计算顺序带来的误差不可忽略

This post is licensed under CC BY 4.0 by the author.