二進制的小數
規則:小數點後面部分的位權,第 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
};