計算機的小數運算

二進制的小數

規則:小數點後面部分的位權,第 1 位是 2 的-1 次冪、第 2 位是 2 的-2 次冪
這一規律並不僅限於二進制數,在十進制數和十六進制數中也同樣適用
例子
將 1011.0011 轉換爲十進制的數?
圖:
在這裏插入圖片描述

負指數冪的推導
圖:
在這裏插入圖片描述

0 指數冪推導
零指數冪推導:
圖:
在這裏插入圖片描述

無法轉換的小數

//result = 10.000002
    public static void show1(){
        float sum = 0;
        int i;
        for(i = 0; i < 100; i++){
            sum += 0.1;
        }
        System.out.println(sum);
    }

二進制數轉換爲十進制小數對應表
圖:
在這裏插入圖片描述
原因彙總
(1)計算機這個功能有限的機器設備,是無法處理無限循環的小數的
(2)不管增加多少位, 2 的-○○次冪怎麼相加都無法得到 0.1 這個結果(確實存在無法轉換)
(3)無法用十進制數來表示 1/3 是一樣的道理。1/3 就是 0.3333…

浮點數

分類
雙精度浮點數類型用 64 位
單精度浮點數類型用 32 位來表示全體小數

浮點數具體組成
浮點數是指用符號、尾數、基數和指數這四部分來表示的小數
圖:
在這裏插入圖片描述

引用:雙 精 度 浮 點 數 能 夠 表 示 的 正 數 範 圍 是 4.94065645841247×10-324~1.79769313486232×10 308 ,負 數 範 圍 是-1.79769313486232×10 308 ~ -4.94065645841247×10-324 。 單 精 度 浮 點 數 能 夠 表 示 的 正 數 範 圍 是1.401298×10 -45 ~3.402823×10 38 ,負數範圍是-3.402823×10 38 ~-1.401298×10-45 。
不過,正如正文中所介紹的那樣,在這些範圍中,有些數值是無法正確表示的

符號部分: 是指使用一個數據位來表示數值的符號。該數據位是 1時表示負,爲 0 時則表示“正或者 0”。

尾數部分: 用的是“將小數點前面的值固定爲 1 的正則表達式”
圖:
在這裏插入圖片描述

正則表達式:按照特定的規則來表示數據的形式即爲正則表達式。除小數之外,字符串以及數據庫等

指數部分: 用的則是“EXCESS 系統表現”
好處:使用 8 位二進制數 00000000 - 11111111(十進制數 255)就能夠表示對應的正、負情況了
對應圖:
在這裏插入圖片描述

如何保證計算的精度

迴避策略

無視這些錯誤。根據程序目的的不同,有時一些微小的偏差並不會造成什麼問題
例如:
假設使用計算機設計工業製品。將 100 個長 0.1 毫米的零件連接起來後,其長度並非一定要是10 毫米,10.000002 毫米也沒有任何問題。一般來講,在科學技術計算領域,計算機的計算結果只要能得到近似值就足夠了。那些微小的誤差完全可以忽略掉

把小數轉換成整數來計算

分析:計算機在進行小數計算時可能會出錯,但進行整數計算(只要不超過可處理的數值範圍)時一定不會出現問題

實例:
Decimal的原理就是把小數放大10的N次方倍,將小數點移動到後面,這樣利用都是整數,就保證了精度。

BigDecimal 由任意精度的整數非標度值 和32 位的整數標度 (scale) 組成。如果爲零或正數,則標度是小數點後的位數。如果爲負數,則將該數的非標度值乘以 10 的負scale 次冪。因此,BigDecimal表示的數值是(unscaledValue × 10-scale)。

BCD編碼方式

定義:8421 BCD碼是最基本和最常用的BCD碼,它和四位自然二進制碼相似,各位的權值爲8、4、2、1,故稱爲有權BCD碼。和四位自然二進制碼不同的是,它只選用了四位二進制碼中前10組代碼,即用0000~1001分別代表它所對應的十進制數,餘下的六組代碼不用

好處:相對於一般的浮點式記數法,採用BCD碼,既可保存數值的精確度,又可免去使計算機作浮點運算時所耗費的時間。

例如:”93.14“
9用4位二進制數碼錶示爲:1001
3用4位二進制數碼錶示爲:0011
1用4位二進制數碼錶示爲:0001
4用4位二進制數碼錶示爲:0100
組合得到93.14得BCD碼:10010011.00010100

思路:因爲可以精確的使用二進制數字表示了十進制的數了,那麼相應的四則運算自然亦不成問題

十六進制的使用

方式:只需在數值的開頭加上 0x(0 和 x)就可以表示十六進制數
好處:通過使用十六進制數,二進制數的位數能夠縮短至原來的 1/4。位數變少之後,看起來也就更清晰了

摘取BigDecima 源碼展示:

    private static final long[][] LONGLONG_TEN_POWERS_TABLE = {
        {   0L, 0x8AC7230489E80000L },  //10^19
        {       0x5L, 0x6bc75e2d63100000L },  //10^20
        {       0x36L, 0x35c9adc5dea00000L },  //10^21
        {       0x21eL, 0x19e0c9bab2400000L  },  //10^22
        {       0x152dL, 0x02c7e14af6800000L  },  //10^23
        {       0xd3c2L, 0x1bcecceda1000000L  },  //10^24
        {       0x84595L, 0x161401484a000000L  },  //10^25
        {       0x52b7d2L, 0xdcc80cd2e4000000L  },  //10^26
        {       0x33b2e3cL, 0x9fd0803ce8000000L  },  //10^27
        {       0x204fce5eL, 0x3e25026110000000L  },  //10^28
        {       0x1431e0faeL, 0x6d7217caa0000000L  },  //10^29
        {       0xc9f2c9cd0L, 0x4674edea40000000L  },  //10^30
        {       0x7e37be2022L, 0xc0914b2680000000L  },  //10^31
        {       0x4ee2d6d415bL, 0x85acef8100000000L  },  //10^32
        {       0x314dc6448d93L, 0x38c15b0a00000000L  },  //10^33
        {       0x1ed09bead87c0L, 0x378d8e6400000000L  },  //10^34
        {       0x13426172c74d82L, 0x2b878fe800000000L  },  //10^35
        {       0xc097ce7bc90715L, 0xb34b9f1000000000L  },  //10^36
        {       0x785ee10d5da46d9L, 0x00f436a000000000L  },  //10^37
        {       0x4b3b4ca85a86c47aL, 0x098a224000000000L  },  //10^38
    };
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章