前言
结合第四篇观看 效果更好^^
数值型分为两类
- 定点数
- 整数
- 小数
- 浮点数
注意:小数点不用占用二进制位
第一部分 编码
1.小数的二进制表示
- 位置计数法:小数点左边的权重是正指数,右边的数是负指数,如图
由此可知,数字形如 0.11111…… (二进制数) 是一个十分接近但小于1的数字 - 由于这种缘故 可表示的数字精度有限,只能精确的表示 x/2^k 这种形式的数字
2.编码有理数
- 采用 v = x × 2^𝑦 的方式
- 这种方式在v的绝对值远大于0或远小于1时有用
3.浮点数的表示(重点)
- 数字的形式表示
- s 符号位:符号位 决定正负
- M 尾数:决定数字的精度,一个小数,通常在[1.0,2.0) 或 [0.0, 1.0)
- E 阶码:决定数字的范围
- 编码方式
- 符号位-阶码-尾数
- 符号位-阶码-尾数
- 几种精度的浮点数(常考32位)
-
单精度:32位
-
双精度:64位
-
扩展精度:80位(仅Intel支持)
-
4.IEEE 754 标准(浮点数编码)
规格化数
-当 exp ≠ 000…0 且 exp ≠ 111…1 时
- 阶码Exp:E = Exp – Bias
- E :真值 即真实值乘以的2的指数
- Bias: bias = 2^k‐1 – 1, k是exp的位宽(因此可知这是固定的,32位是127,64位是1023)
- 尾数M:M = 1.xxx….x (二进制数)
- 包含一个隐式前置的1,即小数点前面的1(这个1存在但不会记录到编码上,相当于节省了一位^^)
- xxx…x: 为frac域的各位的编码
- 最小值:frac = 000…0 (M = 1.0 )
- 最大值:frac = 111…1 (M = 2.0 - ε)(上面已经说过了,这个会无限的接近于1,加上小数点前的1就是2-ε)
举个例子吧~
我们现在有一个浮点数
数值为float f = 15213.0
- 转化成二进制就是
15213 = 11101101101101
= 1.1101101101101 × 2 ^13
从这里就可以得到尾数和阶码的信息了
-
尾数是1.1101101101101
补上单精度的位数并去掉前置1就是尾数
11011011011010000000000 -
阶码部分
真实值E是13(2的指数)
Bias是127(32位)
因此Exp是127+13 = 140
转换成二进制就是 10001100
而符号位为0(正数)
因此我们有以下编码
非规格化数
- 当 exp = 000…0 时
- 阶码
- E = - Bias + 1
- 尾数M = 0.xxx…x(二进制)
- 包含一个隐式前置的0
- xxx…x: 为frac域的各位的编码
- 当 exp = 000…0, 且 frac = 000…0 时
- 注意区别:+0 和 -0区别
- 表示 0
- 当 exp = 000…0, 且 frac ≠ 000…0 时
- 非常接近于0.0的数字
- 等间距的
特殊值
- 当 exp = 111…1 时
- 当 exp = 111…1 且 frac = 000…0 时
- 表示无穷 ∞
- 意味着运算出现了溢出
- 正向溢出,或负向溢出
- 当 exp = 111…1 且 frac ≠ 000…0 时
- 不是一个数字
- 表示数值无法确定
- NaN
如图,
第二部分 运算
1.几种舍入模式
这是重点
- 向下舍入
◼ 舍入结果接近但不会大于实际结果 - 向上舍入
◼ 舍入结果接近但不会小于实际结果 - 向 0 舍入
◼ 舍入结果向 0 的方向靠近
◼ 如果为正数,舍入结果不大于实际结果
◼ 如果为负数,舍入结果不小于实际结果
向偶数舍入(重点)
- 浮点数运算默认的舍入模式
◼其他的舍入模式都会统计偏差
◼ 一组正数的总和将始终被高估或低估 - 适用于舍入至小数点后任何位置
◼ 当数字正好处在四舍五入的中间时
◼ 向最低位为偶数的方向舍入
下面是例子
就是四舍五入的偶数版(一般是按照四舍五入,如果在中间的话就向偶数方向舍入)
不同舍入之间的比较
我们可以看一下不同舍入之间的差异
第一行是向偶数舍入
第二行是向零舍入
第三四行向下和向上舍入
2.基本思想
- 首先计算出精确的值
- 将结果调整至目标的精度
◼ 如果阶码值过大,可能会导致溢出
◼ 可能会进行舍入以满足尾数的位宽
3.浮点数乘法
(-1)s1 M1 2E1 × (-1)s2 M2 2E2
- 精确的结果是(-1)s M 2E
- 符号位 (Sign) s:s1^s2
尾数 (Significand) M:M1 ×M2
阶码 (Exponent) E:E1 + E2
- 符号位 (Sign) s:s1^s2
- 修正:
- 符号位 (Sign) s:s1^s2
尾数 (Significand) M: M1 ×M2
阶码 (Exponent) E:E1 + E2
- 符号位 (Sign) s:s1^s2
4.浮点数加法
(-1)s1 M1 2E1 × (-1)s2 M2 2E2(假设E1 > E2)
- 精确的结果 (Exact Result):(-1)s1 M 2E
◼ 符号位 s 和尾数 M:有符号数对齐后相加的结果
◼ 阶码 (Exponent) E:E2 - 修正
- 如果M ≥ 2,右移M,并增大E的值
如果M < 1,左移M k位,然后E减去k
如果E超出范围,溢出
对M进行舍入以满足frac的位宽精度要求
- 如果M ≥ 2,右移M,并增大E的值
5.C语言中的浮点数
- C语言中支持两种精度的浮点数(float单精度 double 双精度)
- 类型转换
- double/float → int
- 截断尾数
- 向0舍入
- 越界和NaN的情况通常设置为Tmin Tmax
- int → double
- 精准转换 因为int的位宽小于53(double)
- int → float
- 浮点数舍入模式(上面介绍的)
- double/float → int
下面是例子
各类型的强制转换结果如下 解释在右^^