Java Double相加出現的怪事

問題的提出:   java

  編譯運行下面這個程序會看到什麼編程

 

[java] view plaincopymvc

  1. public class test {  
  2.     public static void main(String args[]) {  
  3.         System.out.println(0.05 + 0.01);  
  4.         System.out.println(1.0 - 0.42);  
  5.         System.out.println(4.015 * 100);  
  6.         System.out.println(123.3 / 100);  
  7.     }  
  8. };  


你沒有看錯!結果確實是編程語言

 

 

[java] view plaincopyide

  1. 0.060000000000000005     
  2. 0.5800000000000001     
  3. 401.49999999999994     
  4. 1.2329999999999999     

 

 

Java中的簡單浮點數類型float和double不可以進行運算。不光是Java,在其它不少編程語言中也有這樣的問題。在大多數狀況下,計算的結果是準確的,可是多試幾回(能夠作一個循環)就能夠試出相似上面的錯誤。如今終於理解爲何要有BCD碼了。   
  這個問題至關嚴重,若是你有9.999999999999元,你的計算機是不會認爲你能夠購買10元的商品的。   
  在有的編程語言中提供了專門的貨幣類型來處理這種狀況,可是Java沒有。如今讓咱們看看如何解決這個問題。    
    解決方案   
  如今咱們已經能夠解決這個問題了,原則是使用BigDecimal而且必定要用String來夠造。   
  可是想像一下吧,若是咱們要作一個加法運算,須要先將兩個浮點數轉爲String,而後夠形成BigDecimal,在其中一個上調用add方法,傳入另外一個做爲參數,而後把運算的結果(BigDecimal)再轉換爲浮點數。你可以忍受這麼煩瑣的過程嗎?下面咱們提供一個工具類Arith來簡化操做。它提供如下靜態方法,包括加減乘除和四捨五入:工具

 

[java] view plaincopy.net

  1. public static double add(double v1, double v2);  
  2.   
  3.     public static double sub(double v1, double v2);  
  4.   
  5.     public static double mul(double v1, double v2);  
  6.   
  7.     public static double div(double v1, double v2);  
  8.   
  9.     public static double div(double v1, double v2, int scale);  
  10.   
  11.     public static double round(double v, int scale);  

 

[java] view plaincopyblog

  1. package org.nutz.mvc.core;  
  2.   
  3. import java.math.BigDecimal;  
  4.   
  5. public class Arith {  
  6.     // 源文件Arith.java:  
  7.   
  8.     /** 
  9.      * 因爲Java的簡單類型不可以精確的對浮點數進行運算,這個工具類提供精 確的浮點數運算,包括加減乘除和四捨五入。 
  10.      */  
  11.   
  12.     // 默認除法運算精度  
  13.     private static final int DEF_DIV_SCALE = 10;  
  14.   
  15.     // 這個類不能實例化  
  16.     private Arith() {  
  17.     }  
  18.   
  19.     /** 
  20.      * 提供精確的加法運算。 
  21.      *  
  22.      * @param v1 
  23.      *            被加數 
  24.      * @param v2 
  25.      *            加數 
  26.      * @return 兩個參數的和 
  27.      */  
  28.   
  29.     public static double add(double v1, double v2) {  
  30.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  31.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  32.         return b1.add(b2).doubleValue();  
  33.     }  
  34.   
  35.     /** 
  36.      * 提供精確的減法運算。 
  37.      *  
  38.      * @param v1 
  39.      *            被減數 
  40.      * @param v2 
  41.      *            減數 
  42.      * @return 兩個參數的差 
  43.      */  
  44.   
  45.     public static double sub(double v1, double v2) {  
  46.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  47.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  48.         return b1.subtract(b2).doubleValue();  
  49.     }  
  50.   
  51.     /** 
  52.      * 提供精確的乘法運算。 
  53.      *  
  54.      * @param v1 
  55.      *            被乘數 
  56.      * @param v2 
  57.      *            乘數 
  58.      * @return 兩個參數的積 
  59.      */  
  60.   
  61.     public static double mul(double v1, double v2) {  
  62.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  63.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  64.         return b1.multiply(b2).doubleValue();  
  65.     }  
  66.   
  67.     /** 
  68.      * 提供(相對)精確的除法運算,當發生除不盡的狀況時,精確到 小數點之後10位,之後的數字四捨五入。 
  69.      *  
  70.      * @param v1 
  71.      *            被除數 
  72.      * @param v2 
  73.      *            除數 
  74.      * @return 兩個參數的商 
  75.      */  
  76.   
  77.     public static double div(double v1, double v2) {  
  78.         return div(v1, v2, DEF_DIV_SCALE);  
  79.     }  
  80.   
  81.     /** 
  82.      * 提供(相對)精確的除法運算。當發生除不盡的狀況時,由scale參數指 定精度,之後的數字四捨五入。 
  83.      *  
  84.      * @param v1 
  85.      *            被除數 
  86.      * @param v2 
  87.      *            除數 
  88.      * @param scale 
  89.      *            表示表示須要精確到小數點之後幾位。 
  90.      * @return 兩個參數的商 
  91.      */  
  92.   
  93.     public static double div(double v1, double v2, int scale) {  
  94.         if (scale < 0) {  
  95.             throw new IllegalArgumentException(  
  96.                     "The   scale   must   be   a   positive   integer   or   zero");  
  97.         }  
  98.         BigDecimal b1 = new BigDecimal(Double.toString(v1));  
  99.         BigDecimal b2 = new BigDecimal(Double.toString(v2));  
  100.         return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();  
  101.     }  
  102.   
  103.     /** 
  104.      * 提供精確的小數位四捨五入處理。 
  105.      *  
  106.      * @param v 
  107.      *            須要四捨五入的數字 
  108.      * @param scale 
  109.      *            小數點後保留幾位 
  110.      * @return 四捨五入後的結果 
  111.      */  
  112.   
  113.     public static double round(double v, int scale) {  
  114.         if (scale < 0) {  
  115.             throw new IllegalArgumentException(  
  116.                     "The   scale   must   be   a   positive   integer   or   zero");  
  117.         }  
  118.         BigDecimal b = new BigDecimal(Double.toString(v));  
  119.         BigDecimal one = new BigDecimal("1");  
  120.         return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();  
  121.     }  
  122. };  
相關文章
相關標籤/搜索