1.写在前面

我们上一节介绍了正数的加法、减法、乘法、除法,这节博客我们来介绍下浮点数的加法、减法、乘法、除法。

2.浮点运算

除了有符号和无符号的整数外,编程语言还支持小数,在数学中被称作实数。科学记数法,该记数法在小数点左边只有一个数字。科学记数法中整数部分没有前导0的数字称为规格化数,这是一种常用的表示方法。

为了保证二进制数的规格化形式,我们需要一个基数,使得这个二进制数在移位后(相当于增大或减小基数的指数),小数点左侧必须只剩一位非零数。只有以2为基数才符合我们的要求。由于基数不是10,我们还需要一个新的小数点名称:二进制小数点。

支持这种数的计算机运算称为浮点运算,称作浮点是因为它表示二进制小数点不固定的数字,这与整数表示法不太相同。

利用规格化形式的标准科学计数法表示实数有三个优点:

  1. 简化了包含浮点数的数据交换;
  2. 由于都使用统一表示法,简化了浮点运算算法;
  3. 提高了可存储在字中的数据精度,因为无用的前导零占用的位被二进制小数点右边的实数位替代了。

2.1浮点表示

浮点表示的设计者必须在**尾数(该值通常在0和1之间,放置在尾数字段中)的位数大小和指数(在浮点运算的数值表示系统中,放置在指数字段中的值)**的位数大小之间找到一个平衡,因为固定的字大小意味着若一部分增加一位,则另一部分就得减少一位。

增加尾数位数的大小可以提高小数精度,而增加指数位数的大小则可以增加数的表示范围。

浮点数通常占用多个字的长度。下图是RISC-V浮点数的表示方法,其中s是浮点数的符号(1表示负数),指数由8位指数字段(包括指数的符号)表示,尾数由23位数表示。这种表示称为符号和数值,符号与数值的位是相互分离的。

通常来讲,浮点数可以这样表示:

(-1) ^ s * F * 2 ^ E

F是尾数字段中表示的值,而E是指数字段表示的值;之后会对这两个字段之间的确切关系做详细说明。小到2*10-38大到2*1038。计算机都能表示出来。但是它和无穷大不同,所以仍然可能存在数太大而表示不出来的情况。因此,和整点运算一样,浮点运算中也会发生溢出中断。注意这里的溢出表示因指数太大而在指数字段中表示出来。

可能会导致数过大无法表示,可能会导致数过小无法表示,前者表示上溢,后者表示下溢。

为了减少上溢或者下溢发生概率的一种方法提供了另外一种具有更大的指数范围的格式。这种叫做双精度浮点运算。格式如下:

双精度数可以表示实数范围小到2 * 10 ^-308,大到2 * 10 ^ 308。

2.2例外和中断

有些计算机会通过引发例外(中断)来告知问题的出现。中断在本质上是一种非预期的过程调用。造成溢出的指令的地址保存在寄存器中,并且计算机会跳转到预定义的地址以调用相应的例外的处理程序。中断的地址被保存下来,以便在某些情况下可以在执行纠正代码之后继续执行原程序。但是RISC-V计算机不会再上溢或下溢时引发例外,不过,软件可以读取浮点控制和状态寄存器来检测是否发生上溢或下溢。

2.3IEEE754浮点数标准

这些格式并非RISC-V所独有。它们是IEEE754浮点数标准的一部分,1980年以后的几乎所有计算机都遵循该标准。该标准极大地提高了移植浮点程序的简易程度和计算机的运算质量。

为了将更多的位打包到数中,IEEE754让规格化二进制数的前导位1是隐含的。其他的数就是前面的形式,加上隐含的1:

(-1) ^ s * (1 + 尾数) * 2 ^ E

其中,尾数位表示大小在0到1之间的小数,E表示指数字段的值。如果将尾数的各位从左到右依次用s1,s2,s3,…来表示的话,则数的值为:

(-1) ^ s * (1 + (s1 * 2 ^ -1) + (s2 * 2 ^ -2) + (s3 * 2 ^ -3) + (s4 * 2 ^ -4) + ...) * 2 ^ E

IEEE754甚至还有表示无效运算结果的符号,例如0/0或无穷减去无穷。这个符号是NaN,表示不是一个数。

IEEE754的设计者也考虑到,杜宇浮点表示,尤其是进行排序操作时,最好能直接利用已有的整数比较硬件来处理。这就是符号位处于最高位的原因,这样一来就可以快速判定时小于0、大于0,还是等于0。

把指数字段放在有效位之前也简化了利用整数比较指令对浮点数的排序。因为只要两个数的指数符号相同,那么具有更大指数的数一定更大。

负指数对简化排序提出了挑战。如果我们使用2的补码或其他指数为负数时指数字段的最高有效位为1的表示法,负指数反而会显得比较大。例如,1.0 * 2 ^-1以单精度表示为:

以上面方法表示的1.0 * 2 ^ 1看起来倒像更小的二进制数

因此,最理想的表示法是将最小的负指数表示为000…00,并将最大的正指数表示为111…111。这种表示法称作移码表示法。从移码表示的数减去原数就可以得到相应的偏移值,从而由无符号的移码可得真实的值。

IEEE754规定单精度的偏移值为127,因此指数为-1表示-1+127,即126=01111110 +1表示为1 + 127,即128 = 10000000 双精度的指数偏移值为1023,带偏移值的指数意味着一个由浮点数表示的值实际上是:

(-1) ^ s * (1 + 有效位数) * 2 ^ (指数-偏移值)

单精度数的表示范围从:

+-1.00000000000000000000000 * 2 ^ -126

+-1.11111111111111111111111 * 2 ^ +127

我们直接看下面这个例子:用二进制的形式,分别用IEEE754的单精度格式和双精度格式表示浮点数-0.75(十进制)

  1. -0.75(十进制)又可以表示为:

    -3/4(十进制),即-3/2^2(十进制)
    
  2. 用二进制小数又可以表示为:

    -11(二进制)/2^2(十进制), 即-0.11(二进制)
    
  3. 用科学计数法表示为:

    -0.11(二进制)*2^0
    
  4. 用规格化的科学计数法表示为:

    -1.1(二进制) * 2 ^ -1
    
  5. 单精度数标表示为:

    (-1) ^ s * (1 + 有效位数) * 2 ^ (指数 - 127)
    

    从-1.1(二进制) * 2 ^ -1的指数部分减去127可得:

    (-1) ^ s * (1 + 0.1000 0000 0000 0000 0000 000) * 2 ^ (126-127)
    

    因此-0.75(十进制)的单精度二进制表示为:

双进度表示为:

将二进制浮点数转换为十进制浮点数

2.4浮点加法

让我们用科学记数法表示的数的手算加法来说明一下浮点数的加法:9.999 * 10 ^1 + 1.610 * 10 ^ -1。假设有效数位中只能保存4位十进制数字,而指数字段只能保存两位十进制数字。

**第一步:**为了能够对这些数做出正确的加法运算,我们必须将指数较小的数的小数点和指数较大的数的小数点对齐。因此,我们需要处理指数较小的数,即1.610 * 10 ^ -1,让它与具有较大的指数的数的指数相同。我们发现一个非规格化的浮点数可以有多种科学记数法的表示形式,从而可以利用该特性完成指数对齐。

1.610 * 10 ^ -1 = 0.1610 * 10 ^ 0 = 0.01610 * 10 ^ 1

最右边的数是我们想要的版本,因为它的指数与较大数字的指数相等,即9.999 * 10 ^1。因此,第一步将较小数的有效数位进行右移,直到它的指数变得和较大数的指数一样。但是我们只能表示四位十进制数,所以移位之后的数是:

0.016 * 10 ^ 1

**第二步:**将两个数的有效数位相加:

**第三步:**这个和没有用规格化的科学记数法表示,因此要调整为:

10.015 * 10 ^ 1 = 1.0015 * 10 ^ 2

因此,在加法之后,我们必须对和进行移位,适当地调整指数大小,把它变为规格化的形式。这个例子展示了将和右移一位的情况,但是如果一个数是正数而另外一个数是负数,那么得到的和可能有很多前导0,这时需要进行左移操作。每当指数增大或减小时,我们都必须检测上溢或下溢,我们必须确保指数大小没有超过指数字段的表示范围。

**第四步:**由于我们假定有效位数可能只有四位(不包括符号位),所以我们必须对最后结果进行舍入(四舍五入)。请注意,如果我们在舍入的时候运气不好,例如遇到前面各位都是9的情况,那么加上1的和仍不是规格化的,需要再次执行第三步。

举个例子,我们尝试将0.5和-0.4375用二进制相加。

让我们首先看一个这两个数用规格化的科学记数法的二进制表示,假设保持4位精度:

现在我们按照如下的算法执行:

2.5浮点乘法

我们从手工计算以十进制科学记数法表示的浮点乘法开始:1.1110 * 10 ^ 10 * 9.200 * 10 ^ -5

**第一步:**和加法不同,我们通过简单地操作数的的指数相加来计算积的指数:

新的指数 = 10 + (-5) = 5

让我们用移码来表示指数并确保获得相同的结果:10 + 127 = 137 和 -5 + 127 = 122,所以

新的指数 = 137 + 122 = 259

这个结果对于8位指数字段来说太大了,所以肯定有些地方出错了!问题在于偏移值,因为我们在进行指数相加的同时也进行移位值相加:

新的指数 = (10 + 127) + (-5 + 127) = (5 + 2 * 127) = 259

因此,当我们将带偏移值的数相加时,为了得到正确的带偏移值的总和,我们必须从总和中减去一个偏移值:

新的指数 = 137 + 122 -127 = 257 -127 = 132 = 5 + 127

而5就是我们最初计算的指数。

**第二步:**下面开始有效数位部分的相乘:

每个操作数的小数点右侧有三位数字,因此乘积的小数点应该放在从右数第6位有效位前:

10.212000

如果我们只能保留小数点右侧三位数字,则积为10.212 * 10 ^ 5

**第三步:**因为得到的乘积是非规格化的,所以要将其规格化

10.212 * 10 ^ 5 = 1.0212 * 10 ^ 6

此时,我们可以检测上溢和下溢。如果两个操作数都很小,也就是说,如果两者都具有较小的负指数时,则可能发生下溢。

**第四步:**我们假设有效数位只有四位数字(不包括符号位),所以必须将乘积舍入。乘积:

1.0212 * 10 ^ 6

舍入到四位有效数位是:

1.021 * 10 ^ 6

**第五步:**积的符号取决于原始操作数的符号。如果他们符号相同,则积的符号位正;否则,积的符号位负。因此,积:

+1.021 * 10 ^ 6

在加法算法中,和的符号是由有效位数相加的结果来确定的,但是在乘法中,操作数的符号决定了乘积的符号。

二进制浮点乘法

求出0.5和-0.4375的积。

在二进制下,即是要将1.000 * 2 ^ -1 和 -1.110 * 2 ^ -2相乘

**第一步:**将不带偏移值的指数相加:

-1 + (-2) = -3

或使用移码表示为:

(-1 + 127) + (-2 + 127) -127 = (-1 -2) + (127 + 127 -127) = -3 + 127 = 124

**第二步:**有效数位相乘

乘积为1.110000 * 2 ^ -3,但我们需要保留4位有效数字,因此结果为1.110 * 2 ^ -3

**第三步:**现在我们要检查积以确保它是规格化的,然后检查指数是否上溢或下溢。积已经是规格化的了,并且因为127 >= -3 >= -126,所以没有上溢或下溢

**第四步:**对积舍入,结果没有什么影响:

1.110 * 2 ^ -3

**第五步:**因为操作数的符号相反,因此将积的符号设为负。所以,乘积为:

-1.110 * 2 ^ -3

转化为十进制来检查所得结果

-1.110 * 2 ^ -3 = -0.001110 = -0.00111 = -7/2^5 = -7/32 = -0.21875

2.6RISC-V中的浮点指令

有以下这些指令:

  • 单精度浮点加法指令(fadd.s)和双精度浮点加法指令(fadd.d)
  • 单精度浮点减法指令(fsub.s)和双精度浮点减法指令(fsub.d)
  • 单精度浮点乘法指令(fmul.s)和双精度浮点乘法指令(fmul.d)
  • 单精度浮点除法指令(fdiv.s)和双精度浮点除法指令(fdiv.d)
  • 单精度浮点平方根指令(fsqrt.s)和双精度浮点平方根指令(fsqrt.d)
  • 单精度浮点相等指令(feq.s)和双精度浮点相等指令(feq.d)
  • 单精度浮点小于指令(flt.s)和双精度浮点小于指令(flt.d)
  • 单精度浮点小于或等于指令(fle.s)或双精度浮点小于或等于指令(fle.d)

RISC-V的设计者决定添加独立的浮点寄存器。它们被称为f0、f1…、f31。因此,它们包括独立的用于浮点寄存器的取存指令:fld和fsd用于双精度,flw和fsw用于单精度。

单精度寄存器只是双精度寄存器的后半部分。注意,与整点寄存器x0不同,浮点寄存器f0没有硬连接到常数0.

2.7精确算术

和整数能够精确表示最小数和最大数之间的每个数不同,浮点数无法做到真正精确的表示,通常只能用近似值来表示。原因在于,任意两个实数之间都有无穷多个实数,而双精度浮点数能精确表示的最多只有2 ^ 53个数。我们能做的就是获得和实际数字接近的浮点数表示,因此IEEE754提供了几种舍入的方法,让程序员选择想要的近似值。

这里我们引入两个概念,一个是保护位:在浮点运算的中间计算中,保留在右侧的两个额外位的第一位,用于提高舍入精度。一个是舍入位:使中间结果符合浮点格式的方法,目标通常是找到符合格式的最接近的数,它也是在浮点运算的中间运算中保留在右侧的两个额外位的第二位,可以提高舍入精度。

利用保护位进行舍入

求2.56*100和2.34*102相加之和,假设有3位有效十进制位。将结果舍入到用3位有效十进制位能表示的与精确结果最相近的数,首先使用保护位和舍入位,然后不使用、观察区别。

首先,我们必须将较小的数字向右移以对齐指数,所以2.56 * 10 ^ 0变成为 0.0256 * 10 ^2,由于有保护位和舍入位,所以当我们对齐指数时,能够表示两个最低有效位。其中保护位位5,舍入位位6,和为:

总和为2.3656 * 10 ^ 2因为需要舍入2位,所以我们以50为界,如果后两位的值在049之间,则将其直接舍去,如果值在5199之间,则舍入后向高位进1.因此将和舍入到3位有效位的结果为2.37 * 10 ^ 2。

再观察不带保护位和舍入位的情况,会在计算中丢掉2位有效位。新的和为:

结果为2.36 * 10 ^ 2 比前一个结果最后一位小1。

舍入的最坏情况是实际的数刚好在两个浮点表示之间,浮点的精度通常以有效数位中最低有效位的错误位数来衡量,这种衡量方式卑微最后位置单位的数目,即ulp.如果一个数的最低有效位比实际小2,则称少2ulp.在没有上溢、下溢或无效操作引发例外的情况下。

2.8总结

信息的含义不能仅仅通过查看位来确定,同样的位可以表示各种不同的意思。IEEE754标准浮点表示:
( − 1 ) s ∗ ( 1 + 有 效 位 ) ∗ 2 ( 指 数 + 偏 移 量 ) (-1) ^s*(1+有效位)*2^{(指数+偏移量)} (−1)s∗(1+有效位)∗2(指数+偏移量)
几乎总是实数的近似值。计算机系统必须注意将现实世界中的算术和计算机算术之间的差距最小化,程序要有时需要意识到这种近似可能带来的后果。

4.谬误与陷阱

谬误:正如左移指令可以代替一个乘以2的幂的整数,右移等同与除以一个2的幂的整数。

陷阱:浮点加法不满足结合律

谬误:使用与整型数据类型的并行执行策略也使用与浮点数据类型

谬误:只有理论数学家关心浮点精度

5.写在最后

我们主要介绍如何和计算机进行计算,以及浮点数如何表示的。下节博客我们会介绍CPU了。

计算机是如何进行计算的?(二)相关推荐

  1. 大学计算机基础实验指导试题,(大学计算机基础实验指导)模拟试题(二)参考答案...

    (大学计算机基础实验指导)模拟试题(二)参考答案 (非计算机专业A卷) 一.填空题(共20分,每空1分) 1.电子管2.分时系统.实时系统3..txt 4.主码 5.实体.参照.用户定义6.同轴电缆. ...

  2. 计算机思维能力培养的核心是什么,【计算机基础论文】计算机基础教学中计算思维能力培养(共6714字)...

    计算机基础教学中计算思维能力培养 摘要:自C9明确提出大学计算机基础教学的核心任务是培养学生计算思维能力后,计算思维能力培养日益受到重视.但从培养目标.培养方式.培养过程.培养效果来看,还存在诸多问题 ...

  3. 计算思维应用于计算机学科,【计算机教学论文】计算机教学中的计算思维培养(共2667字)...

    摘要:在中职院校内,Excel课程是一门计算机基础学科.在其教学过程中,我们应从问题出发,提出自身的解决策略,来培养学生的计算思维. 关键词:计算思维:体系:思维内涵:职业教育 一.中职院校Excel ...

  4. 选股器用计算机测试利润,ROE+市盈率选股 上周使用计算公式:总得分=营业净利润率+资产负债率+市盈率,来筛选股票。 因为笔者不会计算机编程,在计算历年平均值的时候... - 雪球...

    来源:雪球App,作者: 小叮当当当,(https://xueqiu.com/6206539641/116662823) 上周使用计算公式:总得分=营业净利润率+资产负债率+市盈率,来筛选股票. 因为 ...

  5. 计算机仿真技术应用报告,计算机仿真技术实验报告-实验二

    计算机仿真技术实验报告-实验二 (7页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.9 积分 <仿真技术与应用>实验报告计算机仿真技术实验 ...

  6. 【Educoder python 作业答案】国防科技大学《大学计算机基础》Python控制结构(二)※

    [Educoder python 作业答案]国防科技大学<大学计算机基础>Python控制结构(二)※ 第1关:分支结构基础实训 第2关:循环结构基础实训 第3关:函数基础实训 第4关:控 ...

  7. 二进制在线计算机,计算机进制转换计算

    <计算机进制转换计算>由会员分享,可在线阅读,更多相关<计算机进制转换计算(8页珍藏版)>请在人人文库网上搜索. 1.各种进制转换一.进制的概念在计算机语言中常用的进制有二进制 ...

  8. 49 96用计算机怎样算,时计算工具的认识和用计算器计算..ppt

    时计算工具的认识和用计算器计算..ppt 清代八卦算盘 木制算盘 世界最长算盘10.1米 1946年美国宾夕法尼亚大学经过几年的艰苦努力,研制出世界上第一台电子计算机.随着科学技术的进步,计算机不断更 ...

  9. 运行速度最快的计算机一秒钟能计算多少次,现在速度最快的电脑系统是哪一种...

    公告: 为响应国家净网行动,部分内容已经删除,感谢读者理解. 话题:现在速度最快的电脑系统是哪一种回答:使Windows XP快上几倍的三招,设置起来非常简单,但是文章又不乏实用. 1.减少开机磁盘等 ...

最新文章

  1. python中关于list列表的增删查改操作
  2. Mysql忘记用户密码的解决办法
  3. MySQL带ANY关键字的子查询
  4. wine最小化游戏后无法恢复的问题
  5. Javascript创建对象的几种方式?
  6. lisp语言是最好的语言_Lisp可能不是数据科学的最佳语言,但是我们仍然可以从中学到什么呢?...
  7. C++: 06---构造函数析构函数
  8. linux 删除sysadm用户,linux 用户和组命令整理及详细介绍
  9. .net remoting与web service的区别
  10. python3的包(package)在centos中的安装地址
  11. 有源医疗器械电磁兼容入门知识汇总
  12. 大学一年级计算机科学与技术,计算机科学与技术系授课计划及课程表一年级.pdf...
  13. excel 第3讲:查找、替换与定位
  14. 原笔迹手写实现平滑和笔锋效果之:笔迹的平滑(二)
  15. excel表格打印每页都有表头_表头如何自动编号?日常工作中的表格打印常见问题解答...
  16. 用python自带的tkinter做游戏(一)—— 贪吃蛇 篇
  17. matlab三维实心图,matlab画实心散点图
  18. MATLAB命令大全和矩阵操作大全
  19. Python3爬虫——用BeautifulSoup解析古诗文网
  20. 【stm32】delay详解

热门文章

  1. 微信小程序/校园社区论坛/微信云开发/云函数
  2. 微信公众号图灵机器人开发php,使用图灵机器人api搭建微信聊天机器人php实现,图灵微信聊天机器人...
  3. Linux初学运维5
  4. 青海电大随学随考计算机,[青海电大]17秋随学随考心理学作业4题目
  5. 如何访问集群中指定的服务器,【Nacos源码之配置管理 六】集群模式下服务器之间是如何互相感知的...
  6. 抖音60秒视频权限开通方法
  7. 关于自动化测试的定位及一些思考
  8. 2018-CVPR-Harmonious Attention Network for Person Re-Identification
  9. 香港理工大学王淑君老师课题组招收全奖博士生/实习生
  10. RITnet: Real-time Semantic Segmentation of the Eye for Gaze Tracking