一、bigdecimal宣告
新來同事看到我們**中bigdeciaml用法,感覺比較奇怪,由此引出了這篇文章
使用下面方式宣告bigdecimal時,會出現精度問題
bigdecimal bd3 = new bigdecimal(0.1d);
推薦用法
bigdecimal bd1 = new bigdecimal("0.1");
bigdecimal bd2 = bigdecimal.valueof(1d);
用以上方法就不會出問題精度問題
bigdecimal.valueof() 檢視原始碼就可以知道,也是使用的new bigdecimal("0.1")建構函式
注意:bigdecimal都是不可變的(immutable)的,在進行每一步運算時,都會產生乙個新的物件,所以在做加減乘除運算時千萬要儲存操作後的值。
二、為什麼bigdecimal使用double或float會出現精度問題?
原因:十進位制轉二進位制的演算法導致轉為二進位制時,某些數字會永遠不為零
十進位制轉二進位制方法
整數部分:除以2,取出餘數,商繼續除以2,直到得到0為止,將取出的餘數逆序
小數部分:乘以2,然後取出整數部分,將剩下的小數部分繼續乘以2,然後再取整數部分,一直取到小數部分為零為止。如果永遠不為零,則按要求保留足夠位數的小數,最後一位做0舍1入。將取出的整數順序排列
看了這個我想大家就都明白了,double或float之類的浮點數,轉為二進位制儲存時某些數字會永遠不為零
十進位制轉二進位制例子:
整數部分: 我相信你會,你可以的。不會可以看我下面的參考資料
小數部分:乘以2,取整,小數部分繼續乘以2,取整,得到小數部分0為止,將整數順序排列
0.1x2=0.2 取整0,小數部分是2
0.2x2=0.4 取整0,小數部分是4
0.4x2=0.8 取整0,小數部分是8
0.8x2=1.6 取整1,小數部分是6
0.6x2=1.2 取整1,小數部分是2
。。。。。你會發出與前面重複了,會一直不停迴圈下去
三、為什麼bigdecimal使用string不會出現精度問題
現在我們明白為什麼用double,float 出現出精度問題。現在我們要看一下bigdecimal對string做了什麼不會出現精度問題
首先: 程式就是資料結構與演算法
通過debug構造方法,我們可以了解,bigdecimal底層資料結構主要是由下面四個屬性值組成.
int scale; //有多少位小數(即小數點後有多少位)
int precision; //總工有多少位數字
long intcompact; //字串去掉小數點後,轉為long的值,只有當傳的字串長度小於18時才使用該言
biginteger intval; //當傳的字串長度大於等於18時才使用biginteger表示數字
以new bigdecimal("12.12")為例
scale值為2
precision值為4
intcompact值為1212
intval值為空。之所以為空是因為字串長度沒有超18位,所以不啟用biginteger表示
看到這進而其實大家應該明白了,bigdecimal將string轉為了long或biginteger來進行計算。
四、使用idea debug bigdeciaml原始碼出現的奇怪現象
**:bigdecimal bd1 = new bigdecimal("1");
system.out.println("bd1:" + bd1);
上面的**,不進行debug列印的結果是"bd1:1"
我們在idea中同時在bigdeciaml類的411行打上斷點(**:if (offset + len > in.length || offset < 0) ,並非一定在這裡打上斷點,其實只要是在原始碼中加上斷點能讓這段**走到debug即可,但不要在tostring方法上加),然後debug執行,到了點斷處,可以直接往下走,讓**執行完,你會發現結果是"bd1:0"。
原因是什麼我還不明白,估計是idea的debug存在bug導致該問題產生
五、todo:
加、減、乘、除,每個具體原始碼如何實現
參考:
紙上談兵 佇列 queue
佇列 queue 是乙個簡單而常見的資料結構。佇列也是有序的元素集合。佇列最大的特徵是first in,first out fifo,先進先出 即先進入佇列的元素,先被取出。這一點與棧 stack 形成有趣的對比。佇列在生活中很常見,排隊買票 排隊等車 先到的人先得到服務並離開佇列,後來的人加入到佇...
紙上談兵 佇列 queue
佇列 queue 是乙個簡單而常見的資料結構。佇列也是有序的元素集合。佇列最大的特徵是first in,first out fifo,先進先出 即先進入佇列的元素,先被取出。這一點與棧 stack 形成有趣的對比。佇列在生活中很常見,排隊買票 排隊等車 先到的人先得到服務並離開佇列,後來的人加入到佇...
紙上談兵 棧 stack
棧 stack 是簡單的資料結構,但在計算機中使用廣泛。它是有序的元素集合。棧最顯著的特徵是lifo last in,first out,後進先出 當我們往箱子裡存放一疊書時,先存放的書在箱子下面,我們必須將後存放的書取出來,才能看到和拿出早先存放的書。棧中的每個元素稱為乙個frame。而最上層元素...