[問題] IEEE 754 浮點數運算以及rounding請益

看板C_and_CPP (C/C++)作者 (@@@@@@@@@@@@@@@@@@@)時間5年前 (2020/05/31 14:12), 5年前編輯推噓11(11016)
留言27則, 4人參與, 5年前最新討論串1/1
大家好 小弟目前在修系上計算機方面的課程 老師希望我們寫出一個浮點數的運算單元, 然後以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://www.ptt.cc/bbs/C_and_CPP/M.1590905575.A.34F.html

05/31 14:23, 5年前 , 1F
都告訴你round to nearest even了,就是用那種方式做。
05/31 14:23, 1F

05/31 14:23, 5年前 , 2F
你提的3個都不是老師要求的
05/31 14:23, 2F
那可以請問一下如果要符合要求,小exponent的那個mantissa到底該怎麼移嗎? 因為要對齊大exponent的話,一定會有幾個bit超過mantissa能保存的範圍(23bit) 我有去翻Computer Organization and Design: The Hardware/Software Interface 這本書,但是他舉的例子好像比較接近我提的第(三)種QQ

05/31 14:28, 5年前 , 3F
你得到G,R,S後,要根據他們的值額外做進位,最後依然是2
05/31 14:28, 3F

05/31 14:28, 5年前 , 4F
3bits
05/31 14:28, 4F
那請問我的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 =>和第一個數運算 是這樣子嗎? 在麻煩您解答一下了,感激不盡

05/31 15:01, 5年前 , 5F
不是,rounding 是算完在做的。以位移來說,次方數差超
05/31 15:01, 5F

05/31 15:01, 5年前 , 6F
過25位是不會影響rounding的結果。
05/31 15:01, 6F
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

05/31 15:13, 5年前 , 7F
比方說,你減完得到G是1、R是1,你這結果還要進位才是ro
05/31 15:13, 7F

05/31 15:14, 5年前 , 8F
und to nearest even 的值
05/31 15:14, 8F
我能理解您所說的"做完運算(減完後)"還要再rounding, 但是我的問題比較像是, 在中間過程中,如果有一個數字在移位後, 他的mantissa超過了原本格式所能表示的範圍, 那這些超過的bit要如何處理它們, 才會使我可以正確的運算並且得到正確的結果 然後最後再做rounding呢? 因為如果這幾個bit不正確處理的話,最後運算結果再rounding應該也不會對 所以我目前是卡在中間過程中不知道該如何處理這些超過mantissa的bits QQ

05/31 15:23, 5年前 , 9F
超過的部分在進位前做保留,以硬體來說多幾位元存不是很
05/31 15:23, 9F

05/31 15:23, 5年前 , 10F
大的問題。
05/31 15:23, 10F

05/31 15:29, 5年前 , 11F
像是32位元的無號整數乘法,他會乘完得出64位元的值再取
05/31 15:29, 11F

05/31 15:29, 5年前 , 12F
32位元
05/31 15:29, 12F

05/31 15:41, 5年前 , 13F
我上面的部分有地方講錯,round to nearest even需要看4
05/31 15:41, 13F

05/31 15:41, 5年前 , 14F
個地方,第23位、G、R、S,rounding完會讓第23位爲0。
05/31 15:41, 14F

05/31 15:43, 5年前 , 15F
更正,第23位不一定爲0
05/31 15:43, 15F

05/31 15:48, 5年前 , 16F
進位規則是G and (R or S or 第23位),1的話進位,0的
05/31 15:48, 16F

05/31 15:48, 5年前 , 17F
話捨去
05/31 15:48, 17F
您說的"超過的部分在進位前做保留",意思是不管超過幾位, 運算的時候就是把這些超過的存起來照算嗎? 如果是這樣的話我再算一次的過程是: 第一個數: 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

05/31 16:12, 5年前 , 18F
是這樣算沒錯
05/31 16:12, 18F
太好了!真的非常感謝您不厭其煩的替我解答這麼久! 希望如果有問題的話還可以再請教您一下!謝謝! ※ 編輯: ayn775437403 (1.160.137.74 臺灣), 05/31/2020 16:14:38

05/31 17:41, 5年前 , 19F
運算規則規格書找不到嗎?自己都說 IEEE754 了何不
05/31 17:41, 19F

05/31 17:41, 5年前 , 20F
看看原文
05/31 17:41, 20F
有,我有去翻IEEE Standard for Floating-Point Arithmetic這個規格書 但是似乎都是在講"運算過後的結果如何rounding" 好像沒有提到如果"運算過程中移位後超過mantissa範圍的bit該如何處理" 當然可能是我沒看很仔細 QQ ※ 編輯: ayn775437403 (123.195.195.29 臺灣), 05/31/2020 22:54:52

06/01 00:34, 5年前 , 21F
在運算的時候就當一般的數學計算做 做完後再 rounding
06/01 00:34, 21F

06/01 00:34, 5年前 , 22F
轉回 IEEE754 表示法. 換句話說, 中間步驟做計算時就當
06/01 00:34, 22F

06/01 00:35, 5年前 , 23F
成是普通的數學計算, 不要考慮精度跟表示法的限制
06/01 00:35, 23F
了解,謝謝您的回復 所以不管中間運算過程中的浮點數超過了mantissa所能表示範圍的多少bit 仍然要把它一起加入運算就對了 然後最後算完的結果如果有多出mantissa所能表示的範圍再rounding掉 應該是這樣理解沒錯吧@@? 謝謝 ※ 編輯: ayn775437403 (123.195.195.29 臺灣), 06/01/2020 15:43:18

06/06 15:57, 5年前 , 24F
github上面 testfloat 跟 softfloat 研究一下
06/06 15:57, 24F

06/06 15:59, 5年前 , 25F

06/06 15:59, 5年前 , 26F
Point-Arithmetic/dp/0898714826
06/06 15:59, 26F

06/06 16:00, 5年前 , 27F
google 一下 這本 不到110頁 好懂又實在
06/06 16:00, 27F
文章代碼(AID): #1UqqhdDF (C_and_CPP)
文章代碼(AID): #1UqqhdDF (C_and_CPP)