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. };  
相关文章
相关标签/搜索