计算机中单精度浮点数运算详解

新博客pppppkun

写在前面

在PA_2019fall中有一项任务是完成CPU中的浮点数运算,这也是我第一次认真的思考了一下真实的计算机中CPU是如何进行的浮点数运算

在写PA的过程中一头雾水,从迷茫,到困惑,到弄懂,到完成,中间经历了各种坎坷,又无奈于手上的资料仅仅只有一个Guide和i386,剩下不会的地方全靠百度

于是就诞生了这一篇博客,把其中的过程给大家讲的明明白白的!

预备知识

什么是浮点数?浮点数表示的是一个数字,其小数点所在的位置是不确定的,也就是浮动的,因此称之为浮点数

在IEEE 754标准中,单精度的浮点数由3部分组成

  • 符号位,在首位,用1表示负数,0表示正数
  • 阶码 exponent 部分,一共八位,采用移码形式,偏置常数为127
  • 尾数部分,一共23位。

规格化于非规格化

规格化的数表示阶码部分不是全都为0,其23位的尾数实际上表示了24位,最高缺省位为1。而非规格化的数没有缺省位。

尾数加上最高位可能存在的缺省的1后构成的有效数字称为 significand

实现之前的思考

排除特殊情况

Simple

根据表格我们可以先把边界条件排除掉,比如 +0,-0, +\infty, -\infty,NaN

加减

如何让两个浮点数相加?根据上面的知识我们知道两个浮点数的形式基本可以这样给出 1.ababab*2^{exponent},我们很容易就能想到两个浮点数是不能直接相加的,应该让他们同阶后再将尾数相加,这个操作我们叫对阶

对阶

对阶有两种方式,小阶往大阶对齐和大阶往小阶对齐,该如何选择呢?

不妨考虑一下这样的事情,在IEEE754表示的浮点数中,对于相同的阶数来说,尾数中越靠后面的1对最后结果的影响越小。

在对阶中,如果大阶向小阶看齐,那么实际上是将尾数左移,小阶向大阶看齐的话就是尾数右移。

如果我们选择大阶向小阶看齐,那么我们很容易就将尾数中靠前的1给左移没了,因为尾数一共只有23位,这样对计算造成的误差相当大,所以我们选择小阶向大阶看齐

注:考虑如何减小误差是浮点数运算中非常重要的一环

对阶中的特殊情况

在处理非规格化浮点数的时候,它们的阶码全都是0,但是尾数并非是0,其表示的真实值为 0.f*2^{-126},不能将阶码理解成-127,在后面会讲为什么会有这样的结果。

shift的计算

在此,我们已经可以给出右移的位数shift了,在这里我们假设 fb.exponent>fa.exponent

shift = (fb.exponent==0 ? fb.exponent+1:fb.exponent) - (fa.exponent==0? fa.exponent+1:fa.exponent)

最后我们得到的临时的阶码就是 fb.exponent

流程图

先让我们把目前的东西总结一下,后面结合实际栗子来讲也会更加清晰

流程图

在这个图中,我们可以看到在对阶之前先判断了X,Y的值是否为0,如果不是那就开始对阶

在对阶的过程中,小阶慢慢变大,这会导致尾数右移(前面已经提到过),在尾数右移的过程中,我们有可能把尾数移为23个0,如果是这样,我们简单的判断为是阶数小的数实在是太小了,就像10亿+1,那个1加不加我们可能都没有直观的体验

再接下来,我们对尾数进行相加,这个过程中要考虑符号位,如果是做减法,那就对减数的尾数位采用广义上的 取反加一

相加完后,如果尾数变成0,那结果就是0,如果不是0,那就考虑一下尾数有没有溢出(尾数溢出指相加后最高位缺省位达到了2)。如果溢出了,那我们就右移一次,然后判断一下阶数的情况即可

要是没有溢出,那当然万事大吉,但是我们接下来还需要将我们的浮点数规格化一下,意思是规格化的浮点数为1.ababab*2^{exponent},但是我们计算出来的浮点数可能是0.0000ab*2^{exponent},那么我们需要小数点移位,降低阶数,将最高缺省设置成1

当然,规格化的过程中阶数也有可能等于0,这里需要一次特判。

小小的总结

到这里浮点数的加减基本上已经介绍完了,对于乘除法就很简单了,只需要将指数相加,尾数相乘就行了,当然,其中涉及到的一些溢出情况都需要单独判断,在这里不多做讨论

附加位与舍位

一个贴近生活的栗子

加入你是亿万富翁,你的银行卡中有1000亿元,你每天稳定收入1000元,但是由于银行的计算机用的是上面的实现方法,这1000块钱在放进你的卡中的过程中需要进行对阶,对着对着尾数变成了0,相当于你存进去0块

那么该怎么办呢?当然你可以设置一些if语句,让1000加多点,加到足够影响1000亿的时候再一起加上去,这是目前计算机的一个研究方向之一。

附加位

根据IEEE754的规定,所有浮点数运算的中间结果右边都必须至少保留两位的附加位,依次是保护位(guard,G)和舍入位(round,R),为了进一步提高精度,舍入位的右侧还有一个粘位(sticky,S),只要舍入位右边有任何非0的数字,粘位就是1,否则为0。

我们简称这三位为GRS,下面用一个实例来展示一下它的作用

保护位

x = 1.000..00 * 2^1  y = 1.11...11 * 2^0
// without guard bits
  x = 1.000...00 * 2^1
- y = 0.111...11 * 2^1
  z = 0.000...01 * 2^1
    = 1.000...00 * 2^-22
// with guard bits
  x = 1.000...00 0000 * 2^1
- y = 0.111...11 1000 * 2^1
  z = 1.000...00 0000 * 2^-23

可以很明显的观察到,在多了保护位后,计算结果明显更精确了

但是解决了一个问题后又出现了第二个问题,那就是我们的尾数只有23位,就算我们使用了保护位,也只能保护计算过程中的误差,那么对于结果来说,依然有可能不精确

所以接下来,我们引入舍位

舍位

为了保证运算过程中的最大精确度,我们会把23位+3位附加位的浮点数扩展到64位,相加完后再进行规格化,规格化完后我们要对这三位进行舍入操作。舍入的方法采用就近舍入,中间值4按照奇偶来舍入,确定舍入后,完成尾数的后三位右移操作。

缺陷

我们不妨考虑这个栗子
652.13+(-7.48)=644.65

\\省略对阶
 1 010001100       1 010001100 000000
-0 000000111       0 000000111 011110
 1 010000101       1 010000100 100010
   645.0                  644.0

就算有了舍位,在单精度下我们依然很难给出两个浮点数加减的准确答案。

关于浮点数的表示

如果都是规格化的浮点数,那么我们很容易知道我们是没法表示0的,因为最小就是2^{-127},所以为了表示0,我们将2^{-127}-2^{-127}的和用来表示0,那2^{-127}该怎么办呢?

为了填上0到2^{-127}这段上的实数,我们设置了非规格化的浮点数,并且将2^{-127}2^{-126}的数扩展到了整个0到2^{-126}上,这之间的每个数间隔都是一样的

最大的数为
0.1..1*2^{-126} = (1-2^{-23})*2^{-126}

其中每个数的间隔都是
0.00..1*2^{-126} = 2^{-149}

2^{-126}和最大数之间的距离是
2^{-126} - (1-2^{-23})*2^{-126} = 2^{-149}

Summary

  • Floating-point representation

  • Operations

    • Addition

  • Precision Consideration

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350