IEEE 754 浮點數的表示方法


1、在電氣和電子工程師協會IEEE 754 標准中

  • float單精度浮點數(4個字節,32位)在機器中表示:用1位表示數字的符號(正負號),8位表示指數,23位表示尾數(即小數部分)

  • double雙精度浮點數(8個字節,64位):1位表示符號(正負號),11位表示指數,52位表示尾數

By CodeSheep

浮點數階碼E“指數e的移碼-1”表示,還可以用階碼E的移碼(特殊的移碼)+階碼E的真值(即指數)表示。

階碼的移碼:假設階碼用8個二進制位表示,則該階碼的移碼為 2(n-1) ,但注意這里的移碼是特殊的移碼,僅偏移2(n-1)-1=127

2、浮點數的規格化

同一浮點數表示方式不唯一(如1.5=1.01x2(0) =0.101*2(1)),所以規定當尾數不為0時,向左或向右移動小數點,使得小數點左邊始終為1(即1.M的格式)。


3、單精度浮點數真值

一個規格化32位的浮點數x的真值表示為:x=(-1)(s)x(1.M)x2(e) , e=E-127 , E=e的移碼-1


4、十進制到機器碼

(1)0.5=(0.1)(二進制),符號位s為0,指數為e=-1,規格化后尾數為1.0

單精度浮點數尾數域(從小數點后開始)共23位,右側以0補全,尾數域:

M=[000 0000 0000 0000 0000 0000](二進制)

階碼E:E=[-1](的移碼)-1=[0111 1111](二進制)-1=[0111 1110](二進制)

或者 E=127(2(8-1)-1,特殊的移碼)+(-1)(指數)=126=[0111 1110](二進制)

將符號位s,階碼E和尾數域M存放到指定位置,可得0.5的機器碼為:

0.5=[0011 1111 0000 0000 0000 0000 0000 0000](二進制)

十六進制表示為:0.5=0x3f000000 (0x:表示十六進制,0011:3,1111:f,)


(2)1.5=[1.1](二進制),符號位為0,指數e=0,規格化后尾數為1.1。

尾數域M右側以0補全:M=[100 0000 0000 0000 0000 0000](二進制)

階碼E:E=[0](的移碼)-1=[10000000](二進制)-1=[01111111](二進制)

得1.5的機器碼:1.5=[0011 1111 1100 0000 0000 0000 0000 0000](二進制)

十六進制表示:1.5=0x3fc00000


(3)−12.5=[−1100.1](二進制) ,符號位S為1,指數e為3,規格化后尾數為1.1001,

尾數域M右側以0補全:
M=[100 1000 0000 0000 0000 0000] (二進制)

階碼E:
E=[3](的移碼)−1=[1000 0011](二進制)−1=[1000 0010](二進制)

即-12.5的機器碼:
−12.5=[1100 0001 0100 1000 0000 0000 0000 0000](二進制)

十六進制表示:-12.5=0xc1480000 。

5、機器碼到十進制

若某個浮點數的IEEE 754標准存儲格式為0x41360000,那么其浮點數的十進制數值為多少:

0x41360000=[0 10000010 011 0110 0000 0000 0000 0000]

有上述機器碼可知符號位s=0,指數e=階碼-127=1000 0010-127=130-127=3,或者階碼+1=移碼,移碼變換為原碼求得指數 ,10000010+1=10000011(移碼)=00000011(原碼)=3(指數e)

尾數域為:011 0110 0000 0000 0000 0000,第一個0的左邊隱藏了一個1,即尾數1.M=1.011 0110 0000 0000 0000 0000

於是:x=(-1)(s)x1.Mx2(e)=+(1.011011)x2(3)=+1011.011=(11.375)(十進制)


6、浮點數的特殊情況

(1)0的表示(32位為例)

如果階碼E=0,且尾數M是0,則這個數的真值為+0或-0

+0機器碼為:0 00000000 000 0000 0000 0000 0000 0000

-0機器碼為:1 00000000 000 0000 0000 0000 0000 0000

浮點數不能精確表示0,而是以很小的數來近似表示0,以32位單精度浮點數為例:

x=(-1)(s)x(1.M)x2(e) , e=E-127

+0的機器碼對應的真值為:1.0x2^(-127)

-0的機器碼對應的真值為: -1.0x2^(-127)


(2) ±∞的表示(32位為例)

如果階碼E=255,且尾數M是0,則這個數的真值為+∞或-∞

+∞的機器碼為:0 11111111 000 0000 0000 0000 0000 0000

-∞的機器嗎為:1 11111111 000 0000 0000 0000 0000 0000

x=(-1)(s)x(1.M)x2(e) , e=E-127

+∞的機器碼對應真值為:1.0x2^(128)

-∞的機器碼對應真值為:-1.0x2^(128)


7、浮點數的精度

浮點數的精度是由尾數的位數來決定的:

  • 對於float型浮點數,尾數部分23位,換算成十進制就是 2^23=8388608,所以十進制精度只有6 ~ 7位;
  • 對於double型浮點數,尾數部分52位,換算成十進制就是 2^52 = 4503599627370496,所以十進制精度只有15 ~ 16

例題:以下例題是在java編譯環境下檢測的。

1、為什么以下返的結果為true?

System.out.println(1f==0.99999999f);
//結果返回 true

分析:

1.0(十進制)=1.0(二進制)* 20

0 01111111 0000000 00000000 00000000(二進制)

0x3F800000(十六進制)

0.99999999(十進制)

=0.111 111 111 111 111 111 111 111110(二進制)

(猜測:浮點數的尾數只有23位,事先將第24位加一,把進位加到第23位,結果為1.0000000 00000000 00000000)

(實際上和編譯器有關,當小數點后的23位全為0時,編譯器就當成全0處理,即0.0000000 00000000 00000000)

=0.0000000 00000000 00000000* 20

​ ↓
0 01111111 0000000 00000000 00000000(二進制)
​ ↓
0x3F800000(十六進制)

原因:float型浮點數十進制精度只有6 ~ 7位,而0.99999999f小數點后有8位,超出了精度范圍(猜測產生了進位)。


2、為什么以下返回的結果為`false`?
System.out.println(1f==0.9999999f);
//結果返回 false

分析:

0.9999999(十進制)

=0.1111111 11111111 111111110(二進制)

(第24位為0加一不產生進位,所以結果是小數點后23個1,最后進行規范化處理缺位補0)

=1.111111 11111111 11111110(二進制) * 2-1

​ ↓
0 01111110 1111111 11111111 11111110(二進制)
​ ↓
0x3F7FFFFE(十六進制)


這些只是我個人的理解,可能不是很精確,如有錯誤歡迎指正,相互交流共同進步!

參考文獻

[1] IEEE754 浮點數的表示方法
[2] 都工作兩年了,還不知道浮點數如何轉二進制?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM