簡體   English   中英

浮點舍入不正確

[英]Incorrect floating point rounding

在gcc 4.7.3 ,我的fegetround()函數返回FE_TONEAREST 根據c ++參考 ,這意味着從零開始四舍五入。 本質上,它意味着在乘法后調整尾數的精度時保存移出的最后一位(因為它將是它應該的兩倍)。 然后,將保存的位添加到最終的尾數結果中。

例如,浮點乘法給出以下結果:

0x38b7aad5 * 0x38b7aad5 = 0x3203c5af

乘法后的尾數是

  1011 0111 1010 1010 1101 0101
x 1011 0111 1010 1010 1101 0101
-------------------------------
1[000 0011 1100 0101 1010 1110] [1]000 0101 1001 0101 0011 1001

[23'b]組保持有效數字,而[1'b]組保持最后一位移出。 請注意,結果的尾數是

[000 0011 1100 0101 1010 1111]

最后一位切換為1因為由於舍入模式, [1'b1]組被添加到拼接的尾數( [23'b]組)。

這是一個讓我感到難過的例子,因為它讓我覺得硬件沒有正確地舍入。

0x20922800 * 0x20922800 = 0x1a6e34c (check this on your machine)

  1010 0110 1110 0011 0100 1101
x 1010 0110 1110 0011 0100 1101
-------------------------------
01[01 0011 0111 0001 1010 0110 0][1]00 0000 0000 0000 0000 0000

Final Mantissas:       
Their Result:      01 0011 0111 0001 1010 0110 0
Correct Result(?): 01 0011 0111 0001 1010 0110 1

我整天都在處理二進制文件,所以我可能會錯過這里簡單的東西。 給定的舍入模式,哪個答案是正確的?

當四舍五入到最近時,IEEE指定關系為偶數。 0是偶數, 1是奇數,所以英特爾是正確的。

第一輪到最近的地方缺少一個細節。 向四舍五入到最近(偶數)

IEEE 754標准(第4.3.1節)引用:

roundTiesToEven,最接近無限精確結果的浮點數應交付; 如果包含無法代表的無限精確結果的兩個最近的浮點數同樣接近,那么具有偶數最低位的數字應該被傳遞

在您的第一個示例中,您計算​​(8.75794e-5)的平方(如果表示為32位浮點數)具有以下十六進制模式: 0x38b7aad5

(8.75794e-5)的所有24個有效位是:

0xb7aad5 = 1.0110111_10101010_11010101

現在你得到平方后得到:

1.0000011_11000101_10101110_10000101_10010101_00111001

值得注意的是,在99%的情況下,您的計算將在FPU(可能是x87)上執行,該FPU以80位浮點格式運行。

英特爾®64和IA-32架構軟件開發人員手冊

(使用X87 FPU編程):

當浮點,整數或壓縮BCD整數值從內存加載到任何x87 FPU數據寄存器時,這些值將自動轉換為雙擴展精度浮點格式(如果它們尚未采用該格式)。

現在,您希望將結果存儲在32位浮點數中:

1.[0000011_11000101_10101110]10000101_10010101_00111001

這里是舍入模式很重要的地方。 IEEE 754定義了其中的4個,但讓我們關注默認的(舍入到最近(偶數)),我們在這里討論這個。

既然你的FPU有結果(整個 - 我們有80位格式的64個有效位),它必須執行舍入以適應32位(24個有效位和24位)內的數字。 需要顯式存儲的所有23位都放在上面的括號內。

現在四舍五入到最接近無關甚至在這個特定的情況下 ,由於在支架的右位不能半途而廢之間:

1.[0000011_11000101_10101111]
and
1.[0000011_11000101_10101110]

但他們離我們更近了

1.[0000011_11000101_10101111]

這就是你的結果有效位為0x3203C5AF

現在有問題的結果是平方2.4759832E-19 0x20922800

2.4759832E-19的24個有效位是:

0x922800 = 1.0010010_00101000_0000_0000

和平方:

1.[0100110_11100011_01001100]10000000_00000000_0000000

這里甚至是真正重要的部分。 現在你的價值正介於兩者之間:

1.[0100110_11100011_01001101]
and
1.[0100110_11100011_01001100]

據說超過2個值可以包含您的價值。 從他們那里你現在需要選擇一個(后者因為lsb = 0)。

現在你知道為什么結果的24位是0xA6E34C最近的偶數 )而不是0xA6E34D (最接近奇數)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM