The Hardware Software Interface Section 2 Integer and Floating Point Numbers
课程主页:https://courses.cs.washington.edu/courses/cse351/16sp/
课程资料:
实验部分:https://github.com/vuquangtrong/HW-SW_Interface_Course
实验说明:https://courses.cs.washington.edu/courses/cse351/13sp/lab-0.html
课件:http://academictorrents.com/details/b63a566df824b39740eb9754e4fe4c0140306f4b
课程视频:https://www.bilibili.com/video/BV1Zt411s7Gg?from=search&seid=8781593976070799647
这次回顾第二部分,整型数和浮点数。
第二部分:整型数和浮点数
整数表示:无符号和有符号
假设比特表示为
无符号整数
有符号整数
几个重要值
以$w=16$为例
C中无符号和有符号整数
不同长度的值
不难看出有如下关系
- $|\text{TMin}|=\text{TMax}+1$
- $\text {UMax}=2\times \operatorname{TMax}+1$
C语言中上述常数的使用方式如下
#include <limits.h>
ULONG_MAX
LONG_MAX
LONG_MIN
C中无符号和有符号整数
强制转换规则为:比特表示不变,解释方法改变。
int tx, ty;
unsigned ux, uy;
tx = (int) ux;
uy = (unsigned) ty;
如果在某个表达式中同时有有符号和无符号整数,那么有符号整数被强制转换为无符号整数。
算术和移位
移位
- 左移:$ {x} << {y} $
- 将比特向量$x$左移$y$个位置,扔掉左边多余的部分
- 在右边填$0$
- 右移:$ {x} >> {y} $
- 将比特向量$x$右移$y$个位置,扔掉右边多余的部分
- 逻辑移位
- 左侧填充0
- 算数移位
- 左侧填充符号位($x$最左侧的符号)
- 未定义的行为
- 移位量$<0$或$\ge$单词长度
无符号整数的移位
逻辑移位。
有符号整数的移位
算数移位。
符号拓展
无符号拓展比较简单,直接在前面的比特补$0$即可,有符号拓展比较麻烦,具体如下:
- 任务:
- 给定$w$比特位的有符号整型$x$
- 将其转换为$w+k$比特位有符号整型,并且值相同
- 规则:
- 将符号位复制$k$份
- $X^{\prime}=X_{w-1}, \dots, X_{w-1}, X_{w-1}, X_{w-2}, \dots, X_{0}$
证明如下:
原始的值:
现在的值:
来看一个具体例子:
short int x = 15213;
int ix = (int) x;
short int y = -15213;
int iy = (int) y;
背景:二进制小数
分数二进制小数
转换成十进制的结果为
IEEE浮点标准
浮点数表示
数值形式:
- 符号位$s$确定数字是负数还是正数
- 尾数$M$为属于范围$1\sim 2-\epsilon$或$0\sim 1-\epsilon$的二进制小数
- 阶码$E$是指数
编码
- 最高位s表示符号位$s$
- 阶码字段exp表示$E$
- 小数字段frac表示$M$
根据阶码字段的不同,浮点数可以分为以下几个部分:
下面分别介绍:
规格化的值
- 当$\text{exp}\neq 000\ldots 0$且$\text{exp}\neq 111\ldots 1$称为规格化的值
- 阶码的值为$E=\exp -\text{bias}$
- 其中$\exp$为exp域的无符号值
- $\text {bias}=2^{k-1}-1$,其中$k$为exp域的比特数
- 小数字段隐式的用$1$作为首位:$M=1 .\text{xxx} \ldots \text{x}_{2}$
- $\text{xxx} \ldots \text{x}$:小数域
- 取最小值当$\text{frac}=000\ldots 0(M=1.0)$
- 取最大值当$\text{frac}=111\ldots 1(M=2.0-\epsilon)$
来看一个具体例子:
浮点数$F=15213.0$
尾数:
阶码:
结果:
非规格化的值
此时
- 当$\text{exp}=000\ldots 0$称为规格化的值
- 阶码为$E=1-\text {bias }$
- 小数字段的首位为$0$,即$M=0 .\text{xxx} \ldots \text{x}_{2}$
- 例子
- $\exp =000 \ldots 0, \text {frac}=000 \ldots 0$
- 上述两者均表示$0$
- 注意根据符号位的不同有$+0$和$-0$的区别
- $\exp =000 \ldots 0, \text {frac}\neq000 \ldots 0$
- 可以表示接近于$0.0$的数
- $\exp =000 \ldots 0, \text {frac}=000 \ldots 0$
特殊值
- 当$\text{exp}=111\ldots 1$称为特殊值
- 例1:$\exp =111 \ldots 11, \text {frac}=000 \ldots 0$
- 表示$\infty$
- 表示操作溢出,$s=1$表示$-\infty$,$s=0$表示$+ \infty$
- $1.0 / 0.0=-1.0 /-0.0=+\infty, 1.0 /-0.0=-\infty$
- 例2:$\exp =111 \ldots 01, \text {frac}\neq000 \ldots 0$
- Not-a-Number(NaN)
- 表示计算结果无法表达的情形
- 例如$\text{sqrt}(-1),\infty-\infty,\infty \times 0$
可视化:浮点编码
浮点运算和舍入
浮点数运行的基本想法
- $\mathrm{x}+_\mathrm{f} \mathrm{y}=\operatorname{Round}(\mathrm{x}+\mathrm{y})$
- $\mathrm{x}\times_\mathrm{f} \mathrm{y}=\operatorname{Round}(\mathrm{x}\times\mathrm{y})$
- 基本想法
- 首先计算精确结果
- 使它适合所需的精度
- 如果指数太大可能会溢出
- 可能将其舍入为frac
舍入
考虑几种舍入的方法:
浮点数采用的是向偶数舍入。
向偶数舍入
默认舍入模式
- 其他的舍入模式会产生偏差:一组正数之和将一致地被高估或低估
应用于小数位/比特位
当位于中间值时,进行舍入,使得最低有效位为偶数
例子
| 值 | 舍入 | 原因 |
| ————- | —— | ———————————- |
| 7.8949999 | 7.89 | (Less than half way) |
| 7.8950001 | 7.90 | (Greater than half way) |
| 7.8950000 | 7.90 | (Greater than half way) |
| 7.8850000 | 7.88 | (Half way-round down) |
舍入二进制数
二进制小数
- 如果最低有效位为$0$则表示偶数
- 中间值表示为$100\ldots_2$
例子
舍入到小数点后$2$比特
| 值 | 二进制 | 舍入 | 动作 | 舍入后的值 |
| ———————- | —————— | ————- | ———————————- | —————— |
| $2\frac 3 {32}$ | $10.00011_2$ | $10.00_2$ | $(<1 / 2-\text {down})$ | $2$ | | $2\frac 3 {16}$ | $10.00110_2$ | $10.01_2$ | $(>1 / 2-\text{up})$ | $2\frac 14$ |
| $2\frac 7 {8}$ | $10.11100_2$ | $11.00_2$ | $(1 / 2-\text{up})$ | $3$ |
| $2\frac 5 {8}$ | $10.10100_2$ | $10.10_2$ | $(1 / 2-\text{down})$ | $2\frac 1 2$ |
C中的浮点数
- C中有两种精度的浮点数
- float:单精度
- double:双精度
- int,float,double进行转换时,程序改变比特的模式如下
- double/float转换为int
- 截断分数部分
- 向$0$舍入
- 如果超过NaN范围则没有定义:通常转换为$\text{TMin}$
- 例如$1.999$转换为$1$,$-1.999$转换为$-1$,$1e10$转换为$-21483648$
- int/float转换为double
- 因为double的范围更大,所以保留精确值
- int转换为float
- 数字不会溢出,但是可能会产生舍入(float的frac域没有足够的位表示int)
- double转换成float,可能溢出为$+\infty$或$-\infty$,由于精度的问题还会产生舍入
- double/float转换为int