Java中,基本數據float 和double的包裝類Float和Double都是浮點類型
所以對於浮點數在計算機中的表示方法需要有一個基本了解,否則很難了解清楚Float和Double的實現原理
本文對計算機中的浮點數表示IEEE754標准,進行了簡單介紹
浮點數的表示
IEEE754 標准
因為指數有正有負,指數位中我們就要拿出第一位來指示符號,但是處理起來會不方便
所以給指數的真值 加上 指數偏移值 ,就能保證結果總是一個非負數
標准規定
指數偏移值為 2(e−1) -1 e為指數的位數
|
單精度 指數偏移值為127 對於雙精度 指數偏移值為1023 |
指數無符號數表示的范圍
單精度8位 0~255
雙精度11位 0~2047
|
指數真值也就是實際的值
單精度 -127 ~ 128
雙精度 -1022 ~ 1023
|
不過頭尾 被保留, 會另做他用 ,下面會繼續說明 所以實際的值要去掉頭尾,也就是
單精度 -126 ~ 127
雙精度 -1022 ~ 1023
|
規范化形式
取值范圍
單精度
單精度指數的范圍(指數 - 指數偏移值之后的值 ) 為: -126 ~ 127 |
正數最大值 指數為正數的最大值 127 尾數 也為最大值 全部都是1 也就是23個1 (-1)0 × 1.11111...(23個1) × 2127 也就是 (2−2−23)×2127 |
1.11111...(23個1) = 20 +2-1 +2-2 + ....2-23
公比 q= 1/2 a1 = 20
代入公式
|
正數最小值
指數為負數的最小值 -126
尾數 也為最小值, 全部都是0 也就是23個0
1.0 × 2-126
|
雙精度
雙精度指數的范圍(指數 - 指數偏移值之后的值 ) 為:
-1022 ~ 1023
|
正數最大值
指數為正數的最大值 1023
尾數 也為最大值 全部都是1 也就是52個1
(-1)0 * 1.11111...(52個1) * 21023
也就是
(2−2−52)×21023 (還是等比數列求和)
|
正數最小值
指數為負數的最小值 -1022
尾數 也為最小值, 全部都是0 也就是52個0
1.0 × 2-1022
|
非標准化形式
試想,對於單精度 1.001×2−125 和1.01×2−125, 它們的差值是0.001×2−125=1.0×2−128
兩個數值之間的差小於能夠表示的最小值
也就意味着兩個不相等的數進行減法運算,將會瞬間下溢, 得到的結果將會是0
其實這就是精度不夠的問題
所以又規定了非標准化形式
那么怎么區分什么時候是標准什么時候是非標准呢? 就是使用保留的指數的取值范圍
對於指數部分,如果所有的比特位全都是0 ,那么這就是一個非標准化形式
在非標准化情況下,尾數部分之前有隱含的小數點, 但是小數點之前,隱含的不在是1 而是0 |
對於指數的真值,不再是指數部分表示的無符號數減掉指數偏移量
一旦指數部分為0 (也就是所有的比特位都是0),這就是一個標記符號了,不再有指數大小的含義
這種情況下
指數的真值為 1 - 指數偏移量
單精度為 1-127= -126
雙精度為 1-1023 = -1022
|
單精度 (−1)s × (0.f) × 2-126 雙精度 (−1)s × (0.f) × 2-1022 |
取值范圍
很顯然,對於非標准化形式來說,指數的真值變成了固定值
想要獲得正數的最小值,只需要最后一位為1 其他所有的尾數部分全都是0即可
單精度 | 0.0000...1(23位,最后一位為1) × 2-126 = 2-23 × 2-126 = 2-149 |
雙精度 | 0.0000...1(52位,最后一位為1) × 2-1022 = 2-52 × 2-1022 = 2-1074 |
特殊值
指數部分表示的無符號數,頭尾被保留,用於表示一些特別的含義
對於標准化形式,指數部分 既不是全0 也不是全1
非標准化情況下,指數部分為全0
當指數部分中所有bit的值全是1,f中所有bit的值全是0,表示無窮大
根據符號位來區分正無窮和負無窮
|
當指數部分中所有bit的值全是1,f中所有bit的值不全是0 表示NaN(Not a Number) |
如果 指數 是0 並且 小數部分 是0, 這個數是0 根據符號位區分+0 和 -0 |