先來了解一下浮點數在計算機中是以什么形式存儲的
首先要知道計算機能懂得只有0和1,每一個0和1都占一個位 bit (比特)(Binary Digits):存放一位二進制數,最小的存儲單位。
而對於存放一個有小數點的數是如何存儲的呢?
對於整數部分,會轉換成二進制,使用除2倒取余的方法。
22 / 2 = 11 余0
11 / 2 = 5 余1
5 / 2 = 2 余1
2 / 2 = 1 余0
1 / 2 = 0 余1
22 的二進制轉換就是 10110
而對於小數部分,就會乘2取整數的方法。
0.45 * 2 = 0.9 0
0.9 * 2 = 1.8 1
0.8 * 2 = 1.6 1
0.6 * 2 = 1.2 1
0.2 * 2 = 0.4 0
0.4 * 2 = 0.8 0
0.8 * 2 = 1.6 1
0.6 * 2 = 1.2 1
0.2 * 2 = 0.4 0
……
可以發現0.45轉化成二進制的時候是無限循環的
二進制轉換完成,22.45 --> 10110.011100110......
得到這個二進制浮點數之后,計算機是怎么把他表示為沒有小數點的字符呢?
這就用到了小學使用的科學計數法:
10110.011100110 可以寫為 1.0110011100110
![]()
過程中我們發現,小數的轉換有可能會產生無限循環的情況,想要做的最精確的記錄22.45,計算機需要無限大的空間來記錄01
那么 IEEE標准 就規定:
32位單精度(java中的float),使用32位(bit)來存儲
64位雙精度(double), 使用64位儲存
在Java中,對於浮點類型的數據采用單精度類型(float)和雙精度類型(double)來存儲,float數據占用4個字節32bit,double數據占用8個字節64bit。
那么它們是如何來分配內存的呢?其實不論是float還是double在存儲方式上都是遵從IEEE的規范的,float遵從的是IEEE R32.24 ,而double 遵從的是R64.53。
無論是單精度還是雙進度在存儲中分為三個部分:
1.符號位(Sign):0代表正,1代表負
2.指數位(Exponent):用於存儲科學計數法中的指數數據,並且采用移位存儲
3.尾數部分(Mantissa):尾數部分
其中 float 的存儲方式如下圖所示:

而 double 的存儲方式如下:


![[公式]](/image/aHR0cHM6Ly93d3cuemhpaHUuY29tL2VxdWF0aW9uP3RleD0yJTVFJTdCNCU3RA==.png)