4_如何给出浮点数表示

如何给出浮点数表示

给定一个实数, 如何给出其浮点数表示

  • 基本流程

    • 首先计算出精确值

    • 将其转换为所需的精度

    如果是能够表示成为规格化浮点数的话, 就应该表示为 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 的形式, 这个时候就需要挪一下, 做个后调整

浮点数规格化表示见上节内容

后调整

舍入操作可能引起溢出