您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java Double相加出現的問題有哪些”,在日常操作中,相信很多人在Java Double相加出現的問題有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java Double相加出現的問題有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
編譯運行下面這個程序會看到什么
public class test { public static void main(String args[]) { System.out.println(0.05 + 0.01); System.out.println(1.0 - 0.42); System.out.println(4.015 * 100); System.out.println(123.3 / 100); } };
你沒有看錯!結果確實是
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
Java中的簡單浮點數類型float和double不能夠進行運算。不光是Java,在其它很多編程語言中也有這樣的問題。在大多數情況下,計算的結果是準確的,但是多試幾次(可以做一個循環)就可以試出類似上面的錯誤。現在終于理解為什么要有BCD碼了。
這個問題相當嚴重,如果你有9.999999999999元,你的計算機是不會認為你可以購買10元的商品的。
在有的編程語言中提供了專門的貨幣類型來處理這種情況,但是Java沒有。現在讓我們看看如何解決這個問題。
現在我們已經可以解決這個問題了,原則是使用BigDecimal并且一定要用String來夠造。
但是想像一下吧,如果我們要做一個加法運算,需要先將兩個浮點數轉為String,然后夠造成BigDecimal,在其中一個上調用add方法,傳入另一個作為參數,然后把運算的結果(BigDecimal)再轉換為浮點數。你能夠忍受這么煩瑣的過程嗎?下面我們提供一個工具類Arith來簡化操作。它提供以下靜態方法,包括加減乘除和四舍五入:
public static double add(double v1, double v2); public static double sub(double v1, double v2); public static double mul(double v1, double v2); public static double div(double v1, double v2); public static double div(double v1, double v2, int scale); public static double round(double v, int scale); package org.nutz.mvc.core; import java.math.BigDecimal; public class Arith { // 源文件Arith.java: /** * 由于Java的簡單類型不能夠精確的對浮點數進行運算,這個工具類提供精 確的浮點數運算,包括加減乘除和四舍五入。 */ // 默認除法運算精度 private static final int DEF_DIV_SCALE = 10; // 這個類不能實例化 private Arith() { } /** * 提供精確的加法運算。 * * @param v1 * 被加數 * @param v2 * 加數 * @return 兩個參數的和 */ public static double add(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.add(b2).doubleValue(); } /** * 提供精確的減法運算。 * * @param v1 * 被減數 * @param v2 * 減數 * @return 兩個參數的差 */ public static double sub(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.subtract(b2).doubleValue(); } /** * 提供精確的乘法運算。 * * @param v1 * 被乘數 * @param v2 * 乘數 * @return 兩個參數的積 */ public static double mul(double v1, double v2) { BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.multiply(b2).doubleValue(); } /** * 提供(相對)精確的除法運算,當發生除不盡的情況時,精確到 小數點以后10位,以后的數字四舍五入。 * * @param v1 * 被除數 * @param v2 * 除數 * @return 兩個參數的商 */ public static double div(double v1, double v2) { return div(v1, v2, DEF_DIV_SCALE); } /** * 提供(相對)精確的除法運算。當發生除不盡的情況時,由scale參數指 定精度,以后的數字四舍五入。 * * @param v1 * 被除數 * @param v2 * 除數 * @param scale * 表示表示需要精確到小數點以后幾位。 * @return 兩個參數的商 */ public static double div(double v1, double v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); } /** * 提供精確的小數位四舍五入處理。 * * @param v * 需要四舍五入的數字 * @param scale * 小數點后保留幾位 * @return 四舍五入后的結果 */ public static double round(double v, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); } };
String test = "40.61 , 18588.73, 29925.07, 7986.06, 18639.19, 25914.32, 32907.74, 34165.89, 9724.7, 52777.92"; String[] arr = test.split(","); double sum = 0; for(int i=0;i<arr.length;i++){ sum += Double.parseDouble(arr[i]); } System.out.println(sum);
結果: 230670.22999999998
查了查 沒有深入的了解,大概是java 的double機制,關于精度的問題,若是不出現這種情況,保留小數點后兩位就可以了。或者使用BigDecimal進行計算,另外《effective java》這本書里也提過,double和float 不建議使用商業計算。
補充:原因在于我們的計算機是二進制的。浮點數沒有辦法是用二進制進行精確表示。
我們的CPU表示浮點數由兩個部分組成:指數和尾數,這樣的表示方法一般都會失去一定的精確度,有些浮點數運算也會產生一定的誤差。
如:2.4的二進制表示并非就是精確的2.4。
反而最為接近的二進制表示是 2.3999999999999999。浮點數的值實際上是由一個特定的數學公式計算得到的。
到此,關于“Java Double相加出現的問題有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。