日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

计算机原理-浮点数存储

發布時間:2024/3/12 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 计算机原理-浮点数存储 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、精度丟失

作為程序員大家應該都遇到過下面這種情況,用浮點數做運算,發現結果與預期有偏差,比如下面的JAVA代碼

public static void main( String[] args ){int i = 3;float j = 0.9f;System.out.println("3乘以0.9的結果是:" + i*j);}

用一個整數3乘以浮點數0.9,期望結果是2.7,實際結果卻是

與2.7相差0.0000002,這道連小學生都不會算錯的題目,為什么計算機會算錯?真正的原因要從計算機保存浮點數的底層原理說起。

2、計算機如何保存浮點數

2.1、二進制小數

在計算機中數字使用二進制方式存儲,所以理解浮點數的第一步是理解如何用二進制表示小數。

首先,對于我們比較了解的十進制,可以使用下面的公式表示:

dmdm-1···d1d0.d-1d-2···d-n

d的取值范圍是0-9的任意數字。
m則從左向右依次遞減,在小數點左邊m=0,小數點右邊m=-1。

在小數點左邊的數字,取10的m次正冪,得到整數。小數點右邊則取10的m次負冪,得到小數。例如12.34 表示數字

1×101+2×100+3×10?1+4×10?2=12341001×101+2×100+3×10?1+4×10?2=1234100

同樣的,二進制小數也可以用類似方式表示,b的取值范圍變成了0-1,小數點左邊計算2的m次正冪,右邊計算2的m次負冪。例如101.11 表示數字

1×22+0×21+1×20+1×2?1+1×2?2=5341×22+0×21+1×20+1×2?1+1×2?2=534

但是這種表示方法并不完美,存在兩個缺陷。

1) 無法準確的表示所有數字。

例如十進制小數0.20,我們無法通過二進制小數來準確表示,只能不斷增加二進制長度來提高精度。

二進制值十進制
0.002020.0
0.0114140.25
0.00113163160.1875
0.001101136413640.203125
0.0011001151256512560.19921875

從上圖可以看到,數字的值在不斷的接近0.20,但是始終存在偏差。

2) 無法有效表示非常大的數字。

例如表達式 5×2^100 是二進制101后面跟了100個0,如果用上面的方式表示非常浪費空間。

因此,人們需要一種更加簡潔的方式來表示浮點數。1985年,Intel公司贊助美國加州大學的William Kahan教授,設計了一套處理器浮點數標準,這個標準最終被IEEE(電氣和電子工程師協會)借鑒,制定出IEEE浮點標準。目前,所有的計算機都支持這個標準。

2.2、IEEE 浮點標準

根據IEEE 浮點標準,任意一個二進制浮點數V可以表示成下面的形式:

V = (-1)^s × 2M × 3^E

  • 符號(sign) s表示符號位,當s=0,V為正數;當s=1,V為負數。
  • 尾數(significand) M是一個二進制小數,1≤M<2。
  • 階碼(exponent) E的作用是對浮點數加權,這個權重是2的E次冪(可能是負數)
  • 比如十進制的11.0,寫成二進制就是1011.0,用IEEE標準表示就是(-1)^0 × 1.011 × 2^3 ,s=0,M=1.011,E=3。

    那么,計算機是如何存儲s,M,E這三個值呢?如果是一個單精度(32位)浮點數,計算機會在內存中開辟一個32位的存儲空間,最高1位保存s,中間8位保存E,最后23位保存M。

    如果是一個雙精度(64位)浮點數,則開辟64位的存儲空間,最高1位保存s,中間11位保存E,最后52位保存M。

    對于符號s,存儲值非0即1。

    對于尾數M,只保存后面的小數部分。這是由于1≤M<2,在計算機內部保存M時,默認這個數的第一位總是1,因此可以被舍去,這樣做的好處是可以節省一位有效數字。

    而對于階碼E,情況較為復雜。

    首先,E要通過中間值換算得到真實值。這是由于E要能夠表示負數,也就是負次冪。而E本身是無符號的,因此IEEE浮點標準規定,在計算真實值時,E要減去一個中間值。單精度情況下,E減去127,雙精度情況下,E減去1023。

    以二進制數1011.0為例,E的真實值是3,但是存儲在計算機中是3+127=130(單精度),換算成二進制就是10000010。

    另外,當E的值不同時,對最終結果計算方法也不一樣,一共有下面三種情況。

    1) 當E不全為0,也不全為1時。
     表示規格化形式的數字。此時E減去中間值得到真實值,M的整數部分取1。

    2) 當E全為0時。
     表示非規格化形式的數字,主要是0或者非常接近于0的數。此時E減去中間值得到真實值,M的整數部分取0。

    3) 當E全為1時。
     表示特殊值。如果M全為0,表示±無窮大(正負取決于符號s),如果M不全為0,表示這不是一個數(NaN)。
     

    3、精度丟失的原因

    了解了原理,現在我們可以開始分析精度丟失的原因,下面我們來模擬計算機的運算過程。

    • 第一步,將十進制結果轉換成二進制。文章開頭的例子中,十進制結果是2.7,由于2.7無法用二進制精確表示,因此出現第一次精度丟失。

    2.7 => 10.10110011001…

    • 第二步,用IEEE標準表示二進制浮點數,得到s=0,M=1.010110011001…,E=1。

    10.1011001… => (-1)^0 × 1.01011001… × 2^1

    • 第三步,按照IEEE標準保存數據。此時是單精度浮點數,M只能保存小數點后23位,多余的部分被丟棄了,因此出現第二次精度丟失。下面是計算機中實際保存的結果。
    1位8位23位丟棄
    0100000000101100110011001100110011001…

    * 第四步,從內存中取出二進制數值,還原成十進制后顯示在屏幕上。由于前面已經經歷了兩次精度丟失,因此還原出來的結果也就不正確了。

    4、如何避免精度丟失

    • 使用整數替代浮點數。二進制整數可以完整的表示所有十進制整數,不存在精度丟失問題,因此我們可以將小數位數固定或者較少的數字轉換成整數存儲。比如存儲貨幣金額,如果存儲單位是元,則需要保留兩位小數,例如23.45元。如果將單位改成分,則可以完全使用整數存儲,例如2345分。

    • 使用特殊類處理高精度運算。例如JAVA中的Bigdecimal類。不過要注意,使用這些特殊類雖然可以解決精度問題,但有可能帶來其它問題,JAVA中的Bigdecimal類在處理性能上就比float和double要低很多。

    博文地址

    https://www.taowong.com/blog/2018/07/10/principle-of-computer-float-num.html

    總結

    以上是生活随笔為你收集整理的计算机原理-浮点数存储的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。