作者ayn775437403 (@@@@@@@@@@@@@@@@@@@)
看板C_and_CPP
标题[问题] IEEE 754 浮点数运算以及rounding请益
时间Sun May 31 14:12:52 2020
大家好
小弟目前在修系上计算机方面的课程
老师希望我们写出一个浮点数的运算单元,
然後以IEEE 754 单精度浮点数为标准,rounding方式是round to nearest even
而老师给的测资都是标准二进位浮点数的格式了,不用自己再转为IEEE 754浮点数
即输入会像是这样:
0 10010011 0000 0000 0000 0000 1111 111
| |------| |--------------------------|
sign exponent mantissa
而我在写之前想要先确定一下自己观念对不对
不然到时候观念不对怕浪费太多时间改程式
所以想要问一个运算的问题:
(以IEEE 754 单精度浮点数为例
,即1个sign bit,8个 exponent bit,23个mantissabit)
两个浮点数在算加减法的时候,exponent小的mantissa要对齐exponent大的mantissa
也就是要看两个浮点数的exponent差距多少来看mantissa要移位多少
那如果exponent小的那个的mantissa在移位过後超过mantissa所能表示的范围
要把超过范围的那几个bit一起算,还是要舍去呢?
举例来说
我要算两个浮点数相减
第一个数:
0 10010011 0000 0000 0000 0000 1111 111
| |------| |--------------------------|
sign exponent mantissa
第二个数:
1 10001110 0000 0000 0000 0111 1111 111
| |------| |--------------------------|
sign exponent mantissa
第一个数的exponent换成十进位是147,第二个数的exponent换成十进位是142
而147-127(bias)=20,142-127=15
所以事实上上面两个数可以变为:
第一个数:
1.0000 0000 0000 0000 1111 111 * 2^20
第二个数:
-1.0000 0000 0000 0111 1111 111 * 2^15
因为第二个数比第一个数的次方少五,所以要右移5个bit
那麽问题来了,移完之後是会变成
(一)所有bit都保留,因此共要28bit表示mantissa
-0.0000 1000 0000 0000 0011 1111 1111 *(2^20)
|----|
这五个bit超过23bit
(二)超过23bit之後直接砍掉,因此满足23bit表示mantissa
-0.0000 1000 0000 0000 0011 111 *(2^20)
(三)加入round,guard,sticky三个bit去考虑,因此用25bit表示mantissa
-0.0000 1000 0000 0000 0011 1111 1 且设S=1(因为砍掉後面三个1)
| |
G R
是上面(一)、(二)、(三)的哪一种呢?
因为这三种不同的移位方式会造成最後运算答案都不一样,
所以我想IEEE 754应该会有明确的规范。
我个人是比较倾向於第(三)种,
因为如果是第(一)种的话,两个浮点数若exponent差太多
那就要保存一大堆数字,像是两数的exponent如果差了一百
那小的exponent很可能就要保存一百个0外加原本的23个mantissa
等於要保存123个bit,以硬体的角度而言应该是不会这样设计?
还请各位替我解答一下
老师上课浮点数就只是带过 然後就要我们一周写出来
实在是有点头痛Orz
感谢各位!
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.160.137.74 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1590905575.A.34F.html
1F:推 firejox: 都告诉你round to nearest even了,就是用那种方式做。 05/31 14:23
2F:→ firejox: 你提的3个都不是老师要求的 05/31 14:23
那可以请问一下如果要符合要求,小exponent的那个mantissa到底该怎麽移吗?
因为要对齐大exponent的话,一定会有几个bit超过mantissa能保存的范围(23bit)
我有去翻Computer Organization and Design: The Hardware/Software Interface
这本书,但是他举的例子好像比较接近我提的第(三)种QQ
3F:推 firejox: 你得到G,R,S後,要根据他们的值额外做进位,最後依然是2 05/31 14:28
4F:→ firejox: 3bits 05/31 14:28
那请问我的G,R,S有取错吗?
(G=第24bit,R=第25bit,S=第25bit後所有bit做OR,所以G=1,R=1,S=1)
那您的意思是:
加入round,guard,sticky三个bit去考虑,
-0.0000 1000 0000 0000 0011 1111 1 且设S=1(因为砍掉後面三个1)
| |
G R
而因为G,R = 1
=>进位
=> -0.0000 1000 0000 0000 0011 111
+) 1
----------------------------------------------------
-0.0000 1000 0000 0000 0100 000
=>第二个数在移完之後变成:-0.0000 1000 0000 0000 0100 000 * 2^20
=>和第一个数运算
是这样子吗?
在麻烦您解答一下了,感激不尽
5F:推 firejox: 不是,rounding 是算完在做的。以位移来说,次方数差超 05/31 15:01
6F:→ firejox: 过25位是不会影响rounding的结果。 05/31 15:01
f大不好意思,
如果照您说的"rounding是运算完再做"的话,
那我所说的第二个浮点数:
-1.0000 0000 0000 0111 1111 111 * 2^15
要右移五次方的话,超过mantissa 23bit的那五个bit
到底该怎麽处理,去和第一个浮点数:
1.0000 0000 0000 0000 1111 111 * 2^20
运算完後才有正确的结果呢?
我现在用:
http://weitz.de/ieee/ 这个网站去算我这两个数字
答案会是 1.1111 0000 0000 0001 0111 110 * 2^19
但是我怎麽算都算不出这个结果
不好意思问题很多 但是我真的被这问题困扰很久了QQ
7F:推 firejox: 比方说,你减完得到G是1、R是1,你这结果还要进位才是ro 05/31 15:13
8F:→ firejox: und to nearest even 的值 05/31 15:14
我能理解您所说的"做完运算(减完後)"还要再rounding,
但是我的问题比较像是,
在中间过程中,如果有一个数字在移位後,
他的mantissa超过了原本格式所能表示的范围,
那这些超过的bit要如何处理它们,
才会使我可以正确的运算并且得到正确的结果
然後最後再做rounding呢?
因为如果这几个bit不正确处理的话,最後运算结果再rounding应该也不会对
所以我目前是卡在中间过程中不知道该如何处理这些超过mantissa的bits QQ
9F:推 firejox: 超过的部分在进位前做保留,以硬体来说多几位元存不是很 05/31 15:23
10F:→ firejox: 大的问题。 05/31 15:23
11F:推 firejox: 像是32位元的无号整数乘法,他会乘完得出64位元的值再取 05/31 15:29
12F:→ firejox: 32位元 05/31 15:29
13F:→ firejox: 我上面的部分有地方讲错,round to nearest even需要看4 05/31 15:41
14F:→ firejox: 个地方,第23位、G、R、S,rounding完会让第23位爲0。 05/31 15:41
15F:→ firejox: 更正,第23位不一定爲0 05/31 15:43
16F:→ firejox: 进位规则是G and (R or S or 第23位),1的话进位,0的 05/31 15:48
17F:→ firejox: 话舍去 05/31 15:48
您说的"超过的部分在进位前做保留",意思是不管超过几位,
运算的时候就是把这些超过的存起来照算吗?
如果是这样的话我再算一次的过程是:
第一个数:
0 10010011 0000 0000 0000 0000 1111 111
| |------| |--------------------------|
sign exponent mantissa
第二个数:
1 10001110 0000 0000 0000 0111 1111 111
| |------| |--------------------------|
sign exponent mantissa
化成指数形式:
第一个数:
1.0000 0000 0000 0000 1111 111 * 2^20
第二个数:
-1.0000 0000 0000 0111 1111 111 * 2^15
第二个数右移5BIT
=>-0.0000 1000 0000 0000 0011 1111 1111 *(2^20)
|----|
这五个bit超过23bit,但是保留
然後第一个数的1.mantissa减第二个数的1.mantissa:
1.0000 0000 0000 0000 1111 1110 0000
- 0.0000 1000 0000 0000 0011 1111 1111
---------------------------------------------
0.1111 1000 0000 0000 1011 1110 0001
因此目前算出的答案是:0.1111 1000 0000 0000 1011 1110 0001 * 2^20
接着normalized:1.111 1000 0000 0000 1011 1110 0001 * 2^19
但是1.111 1000 0000 0000 1011 1110 0001 * 2^19
||
GR
而有4bit超过23bit,因此要rounding,而G=0,R=0>舍去
其中我G取第24bit,R取第25bit,S=1
因此最後答案为:1.111 1000 0000 0000 1011 1110 * 2^19
这样子我的运算观念是对的吗?
答案和
http://weitz.de/ieee/ 算出来的一样
但是我怕我会不会是观念错误只是刚好蒙对(像是GR取错之类的)
再请f大帮我看一下了,谢谢您
※ 编辑: ayn775437403 (1.160.137.74 台湾), 05/31/2020 16:13:13
18F:推 firejox: 是这样算没错 05/31 16:12
太好了!真的非常感谢您不厌其烦的替我解答这麽久!
希望如果有问题的话还可以再请教您一下!谢谢!
※ 编辑: ayn775437403 (1.160.137.74 台湾), 05/31/2020 16:14:38
19F:推 alan23273850: 运算规则规格书找不到吗?自己都说 IEEE754 了何不 05/31 17:41
20F:→ alan23273850: 看看原文 05/31 17:41
有,我有去翻IEEE Standard for Floating-Point Arithmetic这个规格书
但是似乎都是在讲"运算过後的结果如何rounding"
好像没有提到如果"运算过程中移位後超过mantissa范围的bit该如何处理"
当然可能是我没看很仔细 QQ
※ 编辑: ayn775437403 (123.195.195.29 台湾), 05/31/2020 22:54:52
21F:推 suhorng: 在运算的时候就当一般的数学计算做 做完後再 rounding 06/01 00:34
22F:→ suhorng: 转回 IEEE754 表示法. 换句话说, 中间步骤做计算时就当 06/01 00:34
23F:→ suhorng: 成是普通的数学计算, 不要考虑精度跟表示法的限制 06/01 00:35
了解,谢谢您的回复
所以不管中间运算过程中的浮点数超过了mantissa所能表示范围的多少bit
仍然要把它一起加入运算就对了
然後最後算完的结果如果有多出mantissa所能表示的范围再rounding掉
应该是这样理解没错吧@@?
谢谢
※ 编辑: ayn775437403 (123.195.195.29 台湾), 06/01/2020 15:43:18
24F:推 remember: github上面 testfloat 跟 softfloat 研究一下 06/06 15:57
26F:→ remember: Point-Arithmetic/dp/0898714826 06/06 15:59
27F:→ remember: google 一下 这本 不到110页 好懂又实在 06/06 16:00