問題重現:
double i = 0.1;
system.out.println(i+i+i);
執行上面的語句,最終的結果是:
很奇怪,並不是想象中的0.3,錯誤在**?
原因:這其實是計算機內部機制導致的問題,具體就是計算機中儲存浮點數的機制,導致浮點數如果參與了運算,那麼就可能會喪失精度,產生預期之外的結果,當然這裡只是可能,有以下運算確實會恰巧復合預期結果。
那麼結論:即盡量不要用double或者float來進行精確運算,會喪失精度。double和float適合科學計算,bigdecimal才適合精確計算。構建bigdecimal用string的引數。所謂的科學計算就是會算出很長的小數,最後按需求取捨就可以了。比如天文學或者化學中的質量測定,都不需要特別精確,取小數點後多少多少位就可以了。但如果是經融或者醫療領域,那就必須精確,不能取捨。
計算機儲存浮點數原理:
正數儲存就是補碼(取反加一)。
浮點數在ieee中也有詳細的表示方式。大致是最高位表示正負,中間的幾位表示尾數,最後的幾位表示指數。
具體過程,首先拿到乙個十進位制的小數,
1,先將其轉換為二進位制的小數,整數部分除二取餘法,小數部分則是乘二取整法;
2,移位,使得小數點的左邊只有乙個1,然後記下移動了多少位,假設是n位,那麼指數部分就是n的二進位制表示,當然,n可正可負;
3,根據正負設定符號位
4,取小數點後面的尾數設定尾數字,因為移位後小數點前面只有乙個1,所以這個1不用記錄,只要記錄小數部分即可;
5,記錄指數部分;
這就是double或者float在底層的實現。
從上面的過程可以知道,在將乙個十進位制的小數的小數部分轉換為二進位制的小數時,除非最後的一位是5,否則是不可能乘盡的,也就意味著這個十進位制的小數是無法用二進位制來精確表示的,如果double參與了運算,那麼結果肯定有很大的概率不是精確的。這就解釋了開始的奇怪結果。要想精確計算最好採用bigdecimal。但是,如果double沒有參與運算,直接列印,結果卻沒有任何問題,這個還沒有深究過。
基礎問題 BigDecimal型別的運算問題
bigdecimal a bigdecimal.zero bigdecimal b bigdecimal.one for int i 0 i 10 i system.out.println a 輸出結果發現 a 一直都是0並沒有發生改變,沒有相加變成我們想要的結果,此時我們看原始碼 看原始碼我們發現...
Java util Double型別運算
public class arithmetic4double 實現浮點數的加法運算功能 param v1 加數1 param v2 加數2 return v1 v2的和 public static double add double v1,double v2 bigdecimal b1 new bi...
資料型別十問
1.什麼是變數?1 其值在其作用域內可以改變的量成為變數。2 乙個變數應該有乙個名字,在記憶體中佔據一定的儲存空間。3 變數在使用前必須要定義,每個變數都有自己的位址。2.變數名和變數值區別是什麼?變數名是在變數的宣告的時候,該名字就和記憶體中一塊位址繫結在一起了。可以通過變數名直接找到對應的記憶體...