怎么免费建立一个网站,电子商务网站建设是学什么,seo黑帽2022,自助网站建设方案目录 1. 小数的二进制转换2. 浮点数的二进制转换3. 浮点数的存储3.1 以fp32为例3.2 规约形式与非规约形式 4. 各种类型的浮点数5. BF16和FP16的区别Ref 1. 小数的二进制转换
十进制小数转换成二进制小数采用「乘2取整#xff0c;顺序排列」法。具体做法是#xff1a;用 2 2… 目录 1. 小数的二进制转换2. 浮点数的二进制转换3. 浮点数的存储3.1 以fp32为例3.2 规约形式与非规约形式 4. 各种类型的浮点数5. BF16和FP16的区别Ref 1. 小数的二进制转换
十进制小数转换成二进制小数采用「乘2取整顺序排列」法。具体做法是用 2 2 2 乘十进制小数可以得到积将积的整数部分取出再用 2 2 2 乘余下的小数部分又得到一个积再将积的整数部分取出如此进行直到积中的小数部分为零或者达到所要求的精度为止。
然后把取出的整数部分按顺序排列起来先取的整数作为二进制小数的高位有效位后取的整数作为低位有效位。 二进制小数转十进制小数则十分简单。我们知道二进制表示整数时最低位代表 2 2 2 的 0 0 0 次方往高位依次是 2 2 2 的 1 1 1 次方 2 2 2 次方 3 3 3 次方。那么对应的二进制数小数点后面最高位则是 2 2 2 的 − 1 -1 −1 次方如下图所示 因此 ( 0.1101 ) 2 1 ⋅ 2 − 1 1 ⋅ 2 − 2 0 ⋅ 2 − 3 1 ⋅ 2 − 4 ( 0.8125 ) 10 (0.1101)_21\cdot2^{-1}1\cdot2^{-2}0\cdot2^{-3}1\cdot2^{-4}(0.8125)_{10} (0.1101)21⋅2−11⋅2−20⋅2−31⋅2−4(0.8125)10。
整数可以使用 2 2 2 的非负幂次的有限和来表示但小数就不一定能够用 2 2 2 的负幂次的有限和来表示了部分情况下可能是无限和。
例如对于小数 0.6 0.6 0.6 而言它的二进制形式为 0. 1001 ‾ 0.\overline{1001} 0.1001是一个无限循环小数循环节是 1001 1001 1001。
计算机只能识别 0 0 0 和 1 1 1这就是为什么我们需要讨论十进制小数到二进制小数的转换。注意到在上述的例子中 0.6 0.6 0.6 转换成二进制后是一个无限循环小数由于计算机内存有限无法存储无限长的数字序列因此在实际存储这类数字时只能存储小数点后的有限位数。这就意味着无论如何存储时都必须进行截断或四舍五入处理而这种操作会引入所谓的「浮点数精度误差」。
很显然对于这类小数能够存储的位数越多相应的精度就越高。这就是为什么 double 类型相比于 float 类型能提供更高精度的原因。 ⚠️ 浮点数存储遵循IEEE 754规范。 为加深理解我们使用Python来实现一遍
def decimal_to_binary(decimal, max_step30):binary 0.cnt 0while decimal ! 0 and cnt max_step:decimal * 2bit int(decimal)binary str(bit)decimal - bitcnt 1return binaryprint(decimal_to_binary(0.8125))
print(decimal_to_binary(0.6))2. 浮点数的二进制转换
粗略地讲一个浮点数由其整数部分和小数部分组成在知道小数的进制转换后我们可以将一个十进制浮点数转换成二进制形式。
以 10.625 10.625 10.625 为例。只需注意到 10.625 10 0.625 8 2 0.5 0.125 2 3 2 1 2 − 1 2 − 3 \begin{aligned} 10.625100.625820.50.125 \\ 2^32^12^{-1}2^{-3} \end{aligned} 10.625100.625820.50.12523212−12−3
于是 ( 10.625 ) 10 ( 1010.101 ) 2 (10.625)_{10}(1010.101)_2 (10.625)10(1010.101)2。我们还可以进一步将其表示成以 2 2 2 为底的科学记数法 1010.101 1.010101 × 2 3 1010.1011.010101\times 2^3 1010.1011.010101×23。
一些其他的例子 3.5 → 1.11 × 2 1 0.8125 → 1.101 × 2 − 1 − 0.6 → − 1. 0011 ‾ × 2 − 1 \begin{aligned} 3.5 \to 1.11\times 2^1 \\ 0.8125 \to 1.101\times 2^{-1} \\ -0.6\to -1.\overline{0011}\times 2^{-1} \\ \end{aligned} 3.50.8125−0.6→1.11×21→1.101×2−1→−1.0011×2−1
由此可见任何正十进制浮点数表示成二进制科学记数法以后一定是 1 1 1 点几尾数乘以 2 2 2 的多少次方指数。对于负数来说就是负 1 1 1 点几尾数乘以 2 2 2 的多少次方指数。因此任意一个二进制浮点数都可以表示成下面的形式 V ( − 1 ) s × M × 2 E (1) V(-1)^s\times M\times 2^E\tag{1} V(−1)s×M×2E(1)
其中 s s s 代表符号位sign s 1 s1 s1 说明是负数 s 0 s0 s0 说明是正数。 M M M 是尾数mantissa E E E 是指数exponent。因此存储一个浮点数只需要存储 s , M , E s,M,E s,M,E 这三部分。 一些发现
尾数 M M M 的最高位总是 1 1 1因此实际存储时只需要存储尾数的小数部分fraction即小数点后面的数字。 M ∈ [ 1 , 2 ) M\in[1, 2) M∈[1,2)。这是因为 M M M 最高位是 1 1 1所以至少是 1.000... 1.000... 1.000...极端情况下是 1.111... 1.111... 1.111...即 1 1 2 1 4 . . . 1\frac12\frac14... 12141...即使尾数达到了 2 2 2即 10.000... 10.000... 10.000...也会被重新规范化到 1.000... 1.000... 1.000...即 1 1 1。 E ∈ Z E\in\mathbb{Z} E∈Z可正可负可为 0 0 0。注意到 M × 2 − 1 ∈ [ 0.5 , 1 ) , M × 2 1 ∈ [ 2 , 4 ) M\times 2^{-1}\in[0.5,1),\;M\times 2^1\in[2,4) M×2−1∈[0.5,1),M×21∈[2,4)。因此在十进制下任何小于 1 1 1 的数转化成二进制后其指数一定小于 0 0 0任何大于等于 2 2 2 的数转化成二进制后其指数一定大于 0 0 0。进一步可知对于任意非零十进制浮点数 x x x将其转化成二进制后其指数为 ⌊ log 2 ∣ x ∣ ⌋ \lfloor \log_2|x|\rfloor ⌊log2∣x∣⌋。只考虑正浮点数负浮点数亦然。由上一条知所有指数将所有的正浮点数 ( 0 , ∞ ) (0,\infty) (0,∞) 划分成若干个互不相交的区间 ( 0 , ∞ ) ⋃ k − ∞ ∞ [ 2 k , 2 k 1 ) (0,\infty)\bigcup_{k-\infty}^{\infty}[2^k,2^{k1}) (0,∞)⋃k−∞∞[2k,2k1)。设有两个符号相同的十进制浮点数 x 1 , x 2 x_1,x_2 x1,x2它们在二进制下的指数分别为 k 1 , k 2 k_1,k_2 k1,k2且 k 1 k 2 k_1k_2 k1k2。若 x 1 , x 2 x_1,x_2 x1,x2 均为正则 x 1 x 2 x_1x_2 x1x2若 x 1 , x 2 x_1,x_2 x1,x2 均为负则 x 1 x 2 x_1x_2 x1x2。这说明我们可以仅靠指数来比较两个浮点数的大小前提是指数不同。 M M M 的位数通常决定了浮点数能表示的精度。例如对于十进制小数 0.6 0.6 0.6 而言将其转化成二进制后能存储的尾数位越多表达自然越精确。 E E E 的位数则决定了浮点数能够表示的数值范围。
3. 浮点数的存储
3.1 以fp32为例
IEEE 754规定的浮点数存储格式如下 最高位是符号位 1 1 1 代表负数 0 0 0 代表正数。接下来的若干位是指数位指数位之后才是尾数位不存储最高位 1 1 1。
以fp3232-bit floating point32位浮点数为例它拥有 1 1 1 位符号位、 8 8 8 位指数位 23 23 23 位尾数位。 8 8 8 位有符号整数的取值范围是 [ − 128 , 127 ] [-128,127] [−128,127]可以表示 256 256 256 个指数。但实际上我们前面说过指数不等时可以仅通过指数来比较两个浮点数的大小。为了简化这个比较手续考虑采用 8 8 8 位无符号整数进行存储这样就能仅通过字典序来比较两个指数的大小了。在该设定下指数的取值范围变成了 [ 0 , 255 ] [0,255] [0,255]。
浮点数中还有三个特殊值 0 , ∞ , NaN 0,\infty,\text{NaN} 0,∞,NaN。IEEE 754规定需要留一些位置用来表示这些特殊值 0 0 0 用来留给 0 0 0 255 255 255 用来留给 ∞ , NaN \infty,\text{NaN} ∞,NaN。挖掉两个位置后指数的取值范围变成了 [ 1 , 254 ] [1,254] [1,254]。注意到此时还没有负指数为了平衡正负指数的个数这里引入指数偏移量 c 127 c127 c127于是有 存储指数 − 127 实际指数 存储指数-127实际指数 存储指数−127实际指数
故知实际指数的范围为 [ − 126 , 127 ] [-126,127] [−126,127]。 一般地设 e e e 为指数位的个数则 c ≜ 2 e − 1 − 1 c\triangleq 2^{e-1}-1 c≜2e−1−1。fp32的指数偏移量为 2 8 − 1 − 1 127 2^{8-1}-1127 28−1−1127。 例如 10.625 10.625 10.625 转化成二进制后指数为 3 3 3那么用来存储的指数值为 127 3 130 1273130 1273130即 10000010 10000010 10000010。尾数部分只需要存储 010101 010101 010101因此 10.625 10.625 10.625 用fp32表示即为 0 ⏟ 1 个符号位 10000010 ⏟ 8 个指数位 01010100000000000000000 ⏟ 23 个尾数位 \underbrace{0}_{1个符号位}\;\underbrace{10000010}_{8个指数位}\;\underbrace{01010100000000000000000}_{23个尾数位} 1个符号位 08个指数位 1000001023个尾数位 01010100000000000000000
那反过来该如何操作呢例如给定一个fp32格式的浮点数 11000001010011000000000000000000首先分离出它的符号位、指数位和尾数位
符号位 1 1 1指数位 10000010 10000010 10000010尾数位 10011000000000000000000 10011000000000000000000 10011000000000000000000
由符号位可知这是一个负数将指数位转换成十进制得到 130 130 130因此实际指数为 130 − 127 3 130-1273 130−1273。由此可知该浮点数的二进制科学记数法表示为 − 1.10011 × 2 3 - 1.10011\times2^3 −1.10011×23从而 − 1.10011 × 2 3 − 1100.11 − ( 2 3 2 2 2 − 1 2 − 2 ) − 12.75 -1.10011\times2^3-1100.11-(2^32^22^{-1}2^{-2})-12.75 −1.10011×23−1100.11−(23222−12−2)−12.75
我们还可以用Python来完成这个互相转化的操作
import structdef binary_to_float(binary_str):assert len(binary_str) 32, only support fp32# 4 bytes, 32 bits.decimal_float int(binary_str, 2).to_bytes(4, big)return struct.unpack(f, decimal_float)[0]def float_to_binary(value):packed_float struct.pack(f, value)binary_str .join(f{byte:08b} for byte in packed_float)return binary_strprint(binary_to_float(11000001010011000000000000000000))
print(float_to_binary(-12.75))3.2 规约形式与非规约形式
回到 ( 1 ) (1) (1) 式已知 M ∈ [ 1 , 2 ) M\in[1,2) M∈[1,2)设有 e e e 个指数位那么存储指数 E ∈ [ 0 , 2 e − 1 ] E\in[0,2^e-1] E∈[0,2e−1]。当 E ∈ [ 1 , 2 e − 2 ] E\in[1, 2^e-2] E∈[1,2e−2] 时此时 ( 1 ) (1) (1) 式又称规约形式。
还是以fp32为例只考虑正数在规约形式下
最小值 M 1 , E 1 − 127 − 126 M1,\,E1-127-126 M1,E1−127−126故 V 2 − 126 ≈ 1.18 × 1 0 − 38 V2^{-126}\approx1.18\times10^{-38} V2−126≈1.18×10−38。最大值 M 1 2 − 1 ⋯ 2 − 23 2 − 2 − 23 , E 254 − 127 127 M12^{-1}\cdots2^{-23}2-2^{-23},\,E254-127127 M12−1⋯2−232−2−23,E254−127127故 V ( 2 − 2 − 23 ) ⋅ 2 127 ≈ 3.40 × 1 0 38 V(2-2^{-23})\cdot2^{127}\approx3.40\times 10^{38} V(2−2−23)⋅2127≈3.40×1038
很显然fp32无法表示低于最小值的数低于最小值的数会被视为 0 0 0下溢。同样地高于最大值的数会被视为 ∞ \infty ∞上溢。
更具体地
用 M 0 , E 0 M0,E0 M0,E0 来表示 0 0 0。用 M 0 , E 2 e − 1 M0,E2^e-1 M0,E2e−1 来表示 ∞ \infty ∞。用 M ≠ 0 , E 2 e − 1 M\neq 0,E2^e-1 M0,E2e−1 来表示 NaN \text{NaN} NaN。
为了让fp32能表示低于最小值的数即更接近0的数并且让从最小规约数向 0 0 0 的过渡更加平滑非规约数便由此引入。这种设计使得浮点数系统能够更细致地处理接近零的小数值。
我们先思考一下如何让fp32来表示小于 2 − 126 2^{-126} 2−126 的数呢显然存储指数 E E E 已经达到了最小值 1 1 1而 M ∈ [ 1 , 2 ) M\in[1,2) M∈[1,2)将 M M M 的隐含最高位由 1 1 1 改为 0 0 0从而 M ∈ [ 0 , 1 ) M\in[0,1) M∈[0,1)我们便可以表示比最小规约数还要小的数。
IEEE 754规定非规约数的实际存储指数为 0 0 0而计算公式则为 1 − c 1-c 1−c其中 c c c 为指数偏移量。并且 M ∈ ( 0 , 1 ) M\in(0,1) M∈(0,1)。当 E 0 , M ≠ 0 E0,M\neq0 E0,M0 时则按照非规约数来解析fp32。
我们来计算一下非规约形式下的最小值和最大值
最小值 M 2 − 23 , E 0 M2^{-23},E0 M2−23,E0 V 2 − 23 ⋅ 2 − 126 2 − 149 ≈ 1.4 × 1 0 − 45 V2^{-23}\cdot 2^{-126}2^{-149}\approx 1.4\times 10^{-45} V2−23⋅2−1262−149≈1.4×10−45。最大值 M 2 − 1 2 − 2 ⋯ 2 − 23 1 − 2 − 23 , E 0 M2^{-1}2^{-2}\cdots2^{-23}1-2^{-23},E0 M2−12−2⋯2−231−2−23,E0 V ( 1 − 2 − 23 ) ⋅ 2 − 126 ≈ 2 − 126 V(1-2^{-23})\cdot 2^{-126}\approx2^{-126} V(1−2−23)⋅2−126≈2−126。 我们还可以进一步计算得到一般形式下的一些结论。设一个浮点数有 e e e 个指数位和 f f f 个尾数位令 c ≜ 2 e − 1 − 1 c\triangleq 2^{e-1}-1 c≜2e−1−1则
规约形式下的最小值 2 1 − c 2^{1-c} 21−c。规约形式下的最大值 ( 2 − 2 − f ) ⋅ 2 c (2-2^{-f})\cdot 2^{c} (2−2−f)⋅2c。非规约形式下的最小值 2 1 − c − f 2^{1-c-f} 21−c−f。非规约形式下的最大值 ( 1 − 2 − f ) ⋅ 2 1 − c (1-2^{-f})\cdot 2^{1-c} (1−2−f)⋅21−c。
可以看出有以下等式成立 非规约形式下的最小值 非规约形式下的最大值 规约形式下的最小值 非规约形式下的最小值非规约形式下的最大值规约形式下的最小值 非规约形式下的最小值非规约形式下的最大值规约形式下的最小值
关于特殊值的一些结论 E E E M M M形式 [ 1 , 2 e − 2 ] [1,2^e-2] [1,2e−2] [ 1 , 2 ) [1,2) [1,2)规约形式 0 0 0 ( 0 , 1 ) (0,1) (0,1)非规约形式 0 0 0 0 0 0零 2 e − 1 2^e-1 2e−1 0 0 0无穷 2 e − 1 2^e-1 2e−1 ≠ 0 \neq0 0NaN
4. 各种类型的浮点数
名称指数位尾数位FP16半精度浮点数 5 5 5 10 10 10BF16Brain Floating 8 8 8 7 7 7FP32单精度浮点数 8 8 8 23 23 23FP64双精度浮点数 11 11 11 52 52 52FP128四精度浮点数 15 15 15 112 112 112
5. BF16和FP16的区别
先使用之前得到的公式计算一下规约形式下的最小值和最大值
类型MinMaxFP16 2 − 14 ≈ 6.10 × 1 0 − 5 2^{-14}\approx 6.10\times10^{-5} 2−14≈6.10×10−5 ( 2 − 2 − 10 ) ⋅ 2 15 65504 (2-2^{-10})\cdot 2^{15}65504 (2−2−10)⋅21565504BF16 2 − 126 ≈ 1.18 × 1 0 − 38 2^{-126}\approx1.18\times10^{-38} 2−126≈1.18×10−38 ( 2 − 2 − 7 ) ⋅ 2 127 ≈ 3.39 × 1 0 38 (2-2^{-7})\cdot2^{127}\approx3.39\times10^{38} (2−2−7)⋅2127≈3.39×1038
BF16和FP32的指数位相同像是从FP32中截取了前16位一样。也正是因为指数位相同使得BF16的数值范围与FP32相似。BF16相比FP16的数值范围更大但是精度会更低深度学习中数值范围的重要性是远大于数值精度的。FP16的数值范围过小容易造成溢出。FP16更多用于需要较高精度但数值范围要求不是特别严格的场合如某些图形处理和较轻量级的神经网络模型推理。 Ref
[1] https://blog.csdn.net/u013250861/article/details/131152163 [2] https://www.paddlepaddle.org.cn/documentation/docs/zh/dev_guides/amp_precision/amp_op_dev_guide_cn.html [3] https://cloud.tencent.com/developer/article/1473541 [4] https://www.runoob.com/w3cnote/decimal-decimals-are-converted-to-binary-fractions.html [5] https://leokongwq.github.io/2017/08/19/computer-how-float-stored.html