點選上方“方志朋”,選擇“設為星标”
回複”666“擷取新整理的面試文章
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SM5ETYiNmNxEjMmR2YhVTMykzY2ATY0IjZzgTOjhDMx8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
來源:
https://blog.csdn.net/yacolspace/article/details/78287394
今天在項目中用到double類型資料加減運算時,遇到了一個奇怪的問題,比如1+20.2+300.03,理論上結果應該是321.23,其實結果并不是這樣。
public double add() {
double number1 = 1;
double number2 = 20.2;
double number3 = 300.03;
double result = number1 + number2 + number3;
System.out.println(result);
return result;
}
列印結果如下:
這是為什麼呢?又該如何解決呢?
在使用Java中double 進行運算時,經常出現精度丢失的問題,總是在一個正确的結果左右偏0.0000**1。float和double隻能用來做科學計算或者是工程計算,在商業計算中我們要用 java.math.BigDecimal。BigDecimal一共有4個夠造方法,我們隻考慮兩個進行比較,分别是
BigDecimal(double val)
Translates a double into a BigDecimal.
BigDecimal(String val)
Translates the String repre sentation of a BigDecimal into a BigDecimal.
上面的API簡要描述相當的明确,而且通常情況下,上面的那一個使用起來要友善一些。我們可能想都不想就用上了,會有什麼問題呢?
現貼出BigDecimal的一個構造函數的文檔供大家參考
解決方法
相信從上面的文檔大家也已經找出了解決方法,在需要精确的表示兩位小數時我們需要把他們轉換為BigDecimal對象,然後再進行運算。
另外需要注意,使用BigDecimal(double val)構造函數時仍會存在精度丢失問題,建議使用BigDecimal(String val)。這就需要先把double轉換為字元串然後在作為BigDecimal(String val)構造函數的參數。轉換為BigDecimal對象之後再進行加減乘除操作,這樣精度就不會出現問題了。這也是為什麼有關金錢資料存儲都使用BigDecimal。
處理double類型資料的加、減、乘、除運算時,使用如下方法:
/**
* 加法運算
* @param m1
* @param m2
* @return
*/
public static double addDouble(double m1, double m2) {
BigDecimal p1 = new BigDecimal(Double.toString(m1));
BigDecimal p2 = new BigDecimal(Double.toString(m2));
return p1.add(p2).doubleValue();
}
/**
* 減法運算
* @param m1
* @param m2
* @return
*/
public static double subDouble(double m1, double m2) {
BigDecimal p1 = new BigDecimal(Double.toString(m1));
BigDecimal p2 = new BigDecimal(Double.toString(m2));
return p1.subtract(p2).doubleValue();
}
/**
* 乘法運算
* @param m1
* @param m2
* @return
*/
public static double mul(double m1, double m2) {
BigDecimal p1 = new BigDecimal(Double.toString(m1));
BigDecimal p2 = new BigDecimal(Double.toString(m2));
return p1.multiply(p2).doubleValue();
}
/**
* 除法運算
* @param m1
* @param m2
* @param scale
* @return
*/
public static double div(double m1, double m2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException("Parameter error");
}
BigDecimal p1 = new BigDecimal(Double.toString(m1));
BigDecimal p2 = new BigDecimal(Double.toString(m2));
return p1.divide(p2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
驗證文章開頭提到的問題是否解決,
public double addDouble() {
double result1 = add(1, 20.2);
double result2 = add(result1, 300.03);
System.out.println("使用BigDecimal時結果值:" + result2);
return result2;
}
列印結果值
跟預想中的結果值一樣,解決了double類型資料加減操作時精度丢失的問題。
熱門内容:
一次SQL查詢優化原理分析
start.aliyun.com正式上線
驚呆了,Spring Boot居然這麼耗記憶體!
兩小時入門Docker
一個基于SpringBoot的項目骨架
Spring Boot注解大全,一鍵收藏了!
面試:高頻面試題:如何保證緩存與資料庫的雙寫一緻性?
SpringBoot記憶體洩露,排查竟這麼難!
double & operator[](int i)_java中double類型精度丢失問題及解決方法
最近面試BAT,整理一份面試資料《Java面試BAT通關手冊》,覆寫了Java核心技術、JVM、Java并發、SSM、微服務、資料庫、資料結構等等。
擷取方式:點“在看”,關注公衆号并回複 666 領取,更多内容陸續奉上。
明天見(。・ω・