本篇先介紹IEEE754標准中針對浮點數的規范,然后以問答形式補充有關浮點數的知識點。
(一)IEEE754標准
IEEE 754 標准即IEEE浮點數算術標准,由美國電氣電子工程師學會(IEEE)計算機學會旗下的微處理器標准委員會發布。
以32位float數據為例,在內存中的存儲形式是1bit的符號位(S),8bit表示指數部分(Exp),23表示小數部分的尾數(Fraction)。
表一 單精度浮點數在內存中存儲形式
1bit符號 |
8bit指數部分 |
23bit尾數 |
符號位——S取0時表示負數,取1時表示負數。
指數部分——使用所謂的偏正值形式表示,而不是補碼表示,即指數部分采用一個無符號的正數值存儲。也就是說指數部分要表示的值等於實際存儲值減去一個固定值(對於單精度float類型,是127)。采用這種方式表示的目的是簡化比較,因為,如果采用補碼表示的話,全體符號位S和Exp自身的符號位將導致不能簡單的進行大小比較。因為指數值的大小從0~255(0和255是特殊值),單精度的指數部分范圍是-127~+128(對應的,-127和128是特殊值)。
尾數部分——23bit尾數僅能表示小數部分的尾數,小數部分最高有效位由指數部分決定,具體見下表。小數部分最高有效位是1的數被稱為正規形式。小數部分最高有效位是0的數被稱為非正規形式,其他情況是特殊值。
表二 單精度浮點數表示規則
符號 |
指數 部分 |
指數部分-127 |
尾數部分 |
小數部分的 最高有效位 |
形式 |
1 |
255 |
128 |
非0 |
沒有 |
NaN |
1 |
255 |
128 |
0 |
沒有 |
負無窮 |
1 |
1~254 |
-126~127 |
任意 |
1 |
正規形式(負數) |
1 |
0 |
-127 |
非0 |
0 |
非正規形式(負數) |
1 |
0 |
-127 |
0 |
沒有 |
負0 |
0 |
0 |
-127 |
0 |
沒有 |
正0 |
0 |
0 |
-127 |
非0 |
0 |
非正規形式(正數) |
0 |
1~254 |
-126~127 |
任意 |
1 |
正規形式(正數) |
0 |
255 |
128 |
0 |
沒有 |
正無窮 |
0 |
255 |
128 |
非0 |
沒有 |
NaN |
按照IEEE標准,除了 NaN 以外,浮點數集合中的所有元素都是有序的。如果把它們從小到大按順序排列好,那順序將會是:負無窮,正規形式(負數)、非正規形式(負數)、負0、正0、非正規形式(正數)、正規形式(正數)、正無窮。
對於64bit的雙精度double類型,在內存中的存儲形式是1bit的符號位(S),11bit表示指數部分(Exp),52bit表示小數部分的尾數(Fraction)。指數部分的偏正值是1023,其他情況跟單精度類似,不再贅述。
(二)浮點數Q&A
1)浮點數可以表示數據的范圍是什么?
不考慮特殊值(無窮大、NaN等),浮點數可以表示的范圍是[-Max,Max]。其中Max是浮點數能表示的最大值,具體值參見表三。
表三 浮點數最大值
浮點類型 |
字節碼 |
16進制表示 |
10進制表示 |
單精度 |
7f7fffff |
0x1.fffffep127 |
3.4028235E38 |
雙精度 |
7fefffffffffffff |
0x1.fffffffffffffp1023 |
1.7976931348623157E308 |
2)浮點數的精度怎樣衡量?
浮點數指數部分Exp的數值決定了浮點數與相鄰浮點數的差值,所以,指數部分越小(單精度最小為-127),即浮點數絕對值越小(也就是浮點數越靠近0),相鄰浮點數的差值越小(單精度最小為2^(-127)),浮點數能表示的有效小數位數越多。反之,指數部分越大(單精度最大為127),即浮點數絕對值越大(也就是浮點數越遠離0),相鄰浮點數的差值越大(單精度最小為2^(127)),浮點數能表示的有效小數位數越少。但是,從科學計算的角度看,不管指數部分的數值是多少,浮點數的有效位數由尾數部分決定,單精度的有效數是7位,雙精度的有效數是16位。
表四 浮點數最小正數
浮點類型 |
字節碼 |
16進制表示 |
10進制表示 |
單精度最小正數 |
00000001 |
0x0.000002p-126 |
1.4E-45 |
雙精度最小正數 |
0000000000000001 |
0x0.0000000000001p-1022 |
4.9E-324 |
3)我們知道,在Java中,存在基本數據類型的自動轉換,比如,直接將一個整形字面量賦給一個float變量。 那么,在自動轉換后,整形的精度會丟失么?
當浮點集中沒有與整形值對應的浮點數時,會將整形值轉化成最接近的浮點值,此時,整形值會丟失精度。例如下面的例子,數值為33554431的整形轉化成單精度浮點數后,變成3.3554432E7,即33554432。
int intValue = Integer.MAX_VALUE >> 6;// 33554431
float floatFromInt = intValue;
System.out.println(floatFromInt);// 3.3554432E7
System.out.println(intValue);// 33554431
最后附查看某些浮點數字節碼、16進制表示、10進制表示的源碼及運行結果。
單精度源碼及結果。

3.3554432E7
33554431
描述 十六進制數 字節碼 十進制數
正 無 窮 Infinity 7f800000 Infinity
最 大 值 0x1.fffffep127 7f7fffff 3.4028235E38
最小正規形式正數 0x1.0p-126 00800000 1.17549435E-38
最大非正規形式值 0x0.8p-126 00400000 5.877472E-39
最 小 正 數 0x0.000002p-126 00000001 1.4E-45
負 無 窮 -Infinity ff800000 -Infinity
規 范 的 NaN NaN 7fc00000 NaN
其 他 的 NaN NaN ffc54321 NaN
雙精度源碼及結果。

描述 十六進制數 字節碼 十進制數
正 無 窮 Infinity 7ff0000000000000 Infinity
最 大 值 0x1.fffffffffffffp1023 7fefffffffffffff 1.7976931348623157E308
最小正規形式正數 0x1.0p-1022 0010000000000000 2.2250738585072014E-308
最大非正規形式值 0x0.8p-1022 0008000000000000 1.1125369292536007E-308
最 小 正 數 0x0.0000000000001p-1022 0000000000000001 4.9E-324
負 無 窮 -Infinity fff0000000000000 -Infinity
規 范 的 NaN NaN 7ff8000000000000 NaN
其 他 的 NaN NaN fff8000000054321 NaN
參考資料:
2、《Java虛擬機規范(Java SE 7)》