目录 Table of Contents
如何给出浮点数表示
给定一个实数, 如何给出其浮点数表示
-
基本流程
-
首先计算出精确值
-
将其转换为所需的精度
如果是能够表示成为规格化浮点数的话, 就应该表示为 1 点 xxx 的形式, 然后乘上 2 的多少次方, 然后你这个点后面的多大长度也就是 2 的多少次方, 因为你最后有一个取值范围的限制, 也就是有个域宽, 所以你就要吻合这个宽度的限制. 这就是所需的精度.
-
有可能会溢出 (如果指数的绝对值很大)
-
有可能会需要完成舍入 (Rounding) 操作
因为就是说你的这个 1 点 xxx 后面这个相当于精确的数字表示的宽度是有限的, 所以你要截断, 也就是去舍入.
-
下面给出了各种舍入的方式
给个例子, 它是用十进制作为例子
各种舍入模式/数据样例 | $1.40 | $1.60 | $1.50 | $2.50 | -$1.50 |
---|---|---|---|---|---|
Zero | $1 | $1 | $1 | $2 | -$1 |
Round down | $1 | $1 | $1 | $2 | -$2 |
Round up | $2 | $2 | $2 | $3 | -$1 |
Nearest Even(default) | $1 | $2 | $2 | $2 | -$2 |
第一个就是 Zero, 说白了就是截掉, 不管你是 1.1 还是 1.9, 反正小数点后面的一刀给它切掉
然后 Round down 和 Round up, 这个我们就不去关注它了, 就是向上舍入和向下舍入
我们主要将最后一种, 向偶数舍入, 就是 Round-To-Even
向偶数舍入 (Round-To-Even)
- 这是计算机内默认的舍入方式, 也成为 "向最接近值的舍入"
- 其他方式会产生系统误差 (statistically biased)
就是计算机内默认的, 碰上这种浮点数表示的时候, 默认的方式, 也成为 "向最接近值的舍入"
这是为什么呢 ?
就是说, 其他方式会产生统计误差, 一般来说就是有四舍五入这个说法. 那么如果碰上一个 .5
的话, 因为 .5
都是进位嘛, 那么这样的话会不会就是进的多了, 所以统计上会出现一个偏差, 就是这整个统计上面就是会多一点.
- 关键的设计决策是确定两个可能结果的中间数值的舍入
- 确保舍入后最低有效数字是偶数
那么计算机方面怎么做呢, 就是说, 确保要向最接近值的舍入
打个比方, 以十进制这种舍入方式来讲的话, 如果你碰上这种 .5
的话, 把它砍掉还是说你要进位, 要确保舍入后, 最低有效数字是偶数
我们还是拿这个十进制做一个例子
数据样例 | 舍入后的数据 |
---|---|
1.2349999 | 1.23 (Less than half way) |
1.2350001 | 1.24 (Greater than half way) |
1.2350000 | 1.24 (Half way-round up) |
1.2450000 | 1.24 (Half way-round down) |
假设我们只保留小数点后两位, 1.2349999 也好, 1.2350001 也好, 小数点百位以后, 就不是 .5
嘛, 或者比 .5
小或者比 .5
大
那这种情况下呢, 就该四舍五入, 这个原理上不变, 那么主要问题在什么地方, 如果正好是 1.235 或者说 1.245 0000 这种情况, 就是正好最后要舍入的那个或者要进位的那个是 .5
的话, 那这种情况怎么处理 ?
所以这个地方要做一个规定, 那它不是简单的四舍五入, 它要判断一下, 判断什么呢, 我要确保我舍入以后的最低有效数据是个偶数.
也就是说在这个例子里面, 百分位我要必须是一个偶数.
那么这样的话, 1.235 需要往前进一位, 如果不进位的话就是最后变为 1.23, 最低有效位就不是偶数了. 所以 1.235 要进位变成 1.24.
那么 1.245 呢, 因为它原来已经是偶数了, 你不能进位, 进位之后就是 1.25 最后是奇数了, 所以它还是 1.24, 就是变成 Round down 向下舍入这种方式.
这个就是计算机内部默认的方式, 就是说你要把一个整数转换成一个浮点数的, 它就是这么来做的.
那么反过来说, 如果你在 C 语言里面, 你如果要把一个浮点数转换成整数的话, 那它就很简单了, 它就把小数点后面砍掉.
刚才拿十进制作为例子就是 Round-To-Even, 那么对于二进制数而言是什么意思呢 ?
-
对于二进制数而言
- "Even" 意味着最低有效数字需为 0
我要确保最低有效数字处理完了之后是 0 而不是 1.
- 而最低有效数字右侧的位串为
10000.....
这个前提刚才说过了, 我什么时候采用这个规范呢, 就是说最低有效位数右侧的位串是 1 后面带全 0, 就相当于它是个
.5
的时候用这个规范.当然不是
.5
的话就是用四舍五入的这种方式. -
实例, 假设把下面这些实数或者说分数
- 舍入到小数点后两位
Value Binary Rounded Action Rounded Value 2又3/32 10.00011B 10.00B (<1/2--down) 2 2又3/16 10.00110B 10.01B (>1/2--up) 2又1/4 2又7/8 10.11100B 11.00B (1/2--up) 3 2又5/8 10.10100B 10.10B (1/2--down) 2又1/2 比方说像第一个, 就是 10.000111B, 这个不需要考虑, 因为你最低有效数字右侧数为是 011, 没有到
.5
嘛, 所以就把它砍掉了第二个就是 10.00110B, 那它大于 100 就是进位
第三个就是 10.11100B, 这肯定是向上进位, 因为它要确保你处理完了之后, 最低有效数字位是个 0.
最后一个 10.10100B, 因为是 100 所以我们要考虑一下, 这个时候应该把它砍掉, 因为要确保最低有效数字位是个 0.
-
具体步骤
- 将数值规格化 (前导 1)
首先将数值规格化, 前导 1 就是转换成
1.xxx
再乘上 2 的多少次方的形式- 舍入 (Round to even) 以便符合尾数的位数要求
然后就是舍入, 就是以 round to even 方式舍入, 来确保尾数符合要求
- 后调整
在之后可能会有一个后调整, 因为你舍入之后, 本来是
1.xxx
的形式, 那么有一个进位之后可能变成10.xxx
的形式, 这个时候就需要挪一下, 做个后调整
浮点数规格化表示见上节内容
后调整
舍入操作可能引起溢出