在
x86/x64
體系裡,由於
x87 fpu
硬體使用擴充套件雙精度格式,因此必然會遇到
single/double precision
格式與double extended-precision
格式之間的互換問題。
轉換為擴充套件雙精度數
當由單精度數或雙精度轉換為擴充套件雙精度數時,
exponent
部分必須基於擴充套件雙精度數的
biased
碼來調整。於是擴充套件雙精度數的
exponent
值為:①
從單精度轉化:
exponent – 127 + 16383。②
從雙精度轉化:
exponent – 1023 + 16383
。而擴充套件雙精度數的
significand
部分,由單
/雙精度數的
significand
部分移植過來。
以單精度數
1.11...×2120
為例,它轉換為擴充套件雙精度的過程如下所示。
單精度數
1.11...×2120
的編碼值為
0x7bffffff
,它的exponent
值為0xf7
(11110111b
),significand
部分全為1值。
於是擴充套件雙精度數的
exponent
值為0xf7
-127 + 16383=0x4077
(1000 0000 0111 0111b
),單精度
23位的
significand
部分直接移到擴充套件雙精度的
bit62
到bit40
位,低40位補0
。最終的擴充套件雙精度編碼值為
0x4077_ffffff00_00000000
。而對於雙精度數來說:
52位的
significand
部分將直接移到擴充套件雙精度的
bit62
到bit11
位。擴充套件雙精度數轉換為單精度數
而從擴充套件雙精度轉換為單
/雙精度數的情形會複雜得多,涉及目標格式的
precison
(精度)問題。當擴充套件雙精度
significand
部分的值超出目標格式的精度時,就會發生
rounded
(捨入)操作,從而引發
precision
異常。要檢查超出精度的
significand
是否為0
值,如下所示。
目標格式
超出精度部分 備註
單精度數
bit 39
~bit 0
是否為0值
雙精度數
bit 10
~bit 0
這部分不為
0值時,就會發生
rounded
操作。下面,我們以擴充套件雙精度數
1.11...×2120
轉化為單精度格式為例進行描述。當
1.11...×2120
為擴充套件雙精度格式時,它的編碼值為
0x4077_ffffffff_ffffffff
。目標格式
exponent
部分的計算如下。
①單精度數:
exponent
-16383+127。②
雙精度數:
exponent
-16383+1023
。這個轉換過程較為複雜,如下所示。
圖中的陰影部分是超出精度的
significand
部分(bit 39
~bit 0
),它的值不為
0,需要進行
rounded
操作,在
x87 fpu
中這個捨入依賴於
rounded
控制位。
ieee754
定義了以下
4種捨入模式。
①
round to nearest
模式:朝±∞(正和負方向的無窮大值)方向捨入。
②
round down模式:正數朝最大
normal
值捨入,負數朝
-∞方向捨入。
③
round up模式:正數朝
+∞方向捨入
,負數朝最大
normal
值捨入。
④
round zero模式:正數和負數都朝最大
normal
值捨入。
上圖中的捨入是朝
+∞方向捨入,如圖所示:
bit 39
的值為1
,它將向
bit 40
進行捨入,效果等於
+1值。目標格式中的
significand
部分捨入的結果值為0。
目標格式的
exponent
部分為擴充套件雙精度的
exponent-16383+127=0xf7
(11110111b
),可是由於
significand
部分還是進製值,因此目標格式的最終
exponent
部分為0xf8
(加上1
值)。因此,最終轉換的單精度值為
0x7c000000
,轉換得到的浮點數是
1.0...×2
121,
結果大於原來的擴充套件雙精度浮點數。
擴充套件雙精度數轉換為雙精度數
這和轉換為單精度數是一致的。在雙精度格式裡,它的精度是
52位,因此超出精度部分為
bit10
到bit0
位。exponent
的計算是擴充套件雙精度的
exponent-16383+1023
。本文節選自《
x86x64
體系探索及程式設計》
電子工業出版社出版
鄧志著
浮點數精度問題
一 例子 首先我們去編譯器試試 double a 1.9 通過新增監視檢視a的值 會發現a的值是1.8999999 二 開始今天的學習 在最開始學c 的時候並沒有對浮點數進行很深入的學習,認為浮點不就是小數嘛,首先在c 的巨集裡面有 flt max 和 flt min 的定義,float是四位元組的...
浮點數精度之謎
話要從業務 裡的bug說起,大致過程是前端運算 2.07 1 之後結果卻是1.0699999999999998,老司機們都知道是浮點數運算的精度丟失導致的,在檢視了下具體 果然處理不當。因此我深究一番,並誕生了此文。此處重點強調兩個認識誤區 首先不得不說說浮點數的表示方法,任何數在計算機面前都會被處...
PHP 浮點數的精度
浮點數的精度有限。儘管取決於系統,php 通常使用 ieee 754 雙精度格式,則由於取整而導致的最大相對誤差為 1.11e 16。非基本數 算可能會給出更大誤差,並且要考慮到進行復合運算時的誤差傳遞。此外,以十進位制能夠精確表示的有理數如 0.1 或 0.7,無論有多少尾數都不能被內部所使用的二...