随笔 - 0  文章 - 3  trackbacks - 0
<2011年5月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

留言簿

文章档案(50)

搜索

  •  

最新评论

Java中的简单浮点数类型float和double不能够进行运算。不光是Java,在其它很多编程语言中也有这样的问题。在大多数情况下,计算的结果是准确的,但是多试几次(可以做一个循环)就可以试出类似上面的错误。现在终于理解为什么要有BCD码了。



这个问题相当严重,如果你有9.999999999999元,你的计算机是不会认为你可以购买10元的商品的。



在有的编程语言中提供了专门的货币类型来处理这种情况,但是Java没有。现在让我们看看如何解决这个问题。







四舍五入



我们的第一个反应是做四舍五入。Math类中的round方法不能设置保留几位小数,我们只能象这样(保留两位):



public double round(double value){



    return Math.round(value*100)/100.0;



}



非常不幸,上面的代码并不能正常工作,给这个方法传入4.015它将返回4.01而不是4.02,如我们在上面看到的



4.015*100=401.49999999999994



因此如果我们要做到精确的四舍五入,不能利用简单类型做任何运算



java.text.DecimalFormat也不能解决这个问题:



System.out.println(new java.text.DecimalFormat("0.00").format(4.025));



输出是4.02



java 代码




  1. import java.math.BigDecimal;      

  2. public class Arith      

  3. {      

  4.  private static final int DEF_DIV_SCALE = 10;      

  5.       

  6.    private Arith()      

  7.    {      

  8.       

  9.       }      

  10.       

  11.       

  12.     /**    

  13.     

  14.      * 提供精确的加法运算。    

  15.     

  16.      * @param v1 被加数    

  17.     

  18.      * @param v2 加数    

  19.     

  20.      * @return 两个参数的和    

  21.     

  22.      */      

  23.       

  24.     public static double add(double v1,double v2)      

  25.    {      

  26.       

  27.         BigDecimal b1 = new BigDecimal(Double.toString(v1));      

  28.       

  29.         BigDecimal b2 = new BigDecimal(Double.toString(v2));      

  30.       

  31.         return b1.add(b2).doubleValue();      

  32.       

  33.         }      

  34.       

  35.    /**    

  36.     

  37.      * 提供精确的减法运算。    

  38.     

  39.      * @param v1 被减数    

  40.     

  41.      * @param v2 减数    

  42.     

  43.      * @return 两个参数的差    

  44.     

  45.      */      

  46.       

  47.     public static double sub(double v1,double v2)      

  48.    {      

  49.       

  50.         BigDecimal b1 = new BigDecimal(Double.toString(v1));      

  51.       

  52.         BigDecimal b2 = new BigDecimal(Double.toString(v2));      

  53.       

  54.         return b1.subtract(b2).doubleValue();      

  55.       

  56.      }      

  57.       

  58.       

  59.   /**    

  60.     

  61.      * 提供精确的乘法运算。    

  62.     

  63.      * @param v1 被乘数    

  64.     

  65.      * @param v2 乘数    

  66.     

  67.      * @return 两个参数的积    

  68.     

  69.      */      

  70.       

  71.     public static double mul(double v1,double v2)      

  72.   {      

  73.       

  74.   BigDecimal b1 = new BigDecimal(Double.toString(v1));      

  75.       

  76.   BigDecimal b2 = new BigDecimal(Double.toString(v2));      

  77.       

  78.   return b1.multiply(b2).doubleValue();      

  79.       

  80.   }      

  81.       

  82.        

  83.   /**    

  84.     

  85.      * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到    

  86.     

  87.      * 小数点以后10位,以后的数字四舍五入。    

  88.     

  89.      * @param v1 被除数    

  90.     

  91.      * @param v2 除数    

  92.     

  93.      * @return 两个参数的商    

  94.     

  95.      */      

  96.       

  97.     public static double div(double v1,double v2)      

  98.   {      

  99.       

  100.         return div(v1,v2,DEF_DIV_SCALE);      

  101.       

  102.         }      

  103.       

  104.        

  105.       

  106.    /**    

  107.     

  108.      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指    

  109.     

  110.      * 定精度,以后的数字四舍五入。    

  111.     

  112.      * @param v1 被除数    

  113.     

  114.      * @param v2 除数    

  115.     

  116.      * @param scale 表示表示需要精确到小数点以后几位。    

  117.     

  118.      * @return 两个参数的商    

  119.     

  120.      */      

  121.       

  122.     public static double div(double v1,double v2,int scale)      

  123.   {      

  124.       

  125.    if(scale<0)      

  126.     {      

  127.       

  128.     throw new IllegalArgumentException("The scale must be a positive integer or zero");      

  129.       

  130.       }      

  131.       

  132.         BigDecimal b1 = new BigDecimal(Double.toString(v1));      

  133.       

  134.         BigDecimal b2 = new BigDecimal(Double.toString(v2));      

  135.       

  136.         return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();      

  137.       

  138.      }      

  139.       

  140.        

  141.       

  142.    /**    

  143.     

  144.      * 提供精确的小数位四舍五入处理。    

  145.     

  146.      * @param v 需要四舍五入的数字    

  147.     

  148.      * @param scale 小数点后保留几位    

  149.     

  150.      * @return 四舍五入后的结果    

  151.     

  152.      */      

  153.       

  154.     public static double round(double v,int scale){      

  155.       

  156.         if(scale<0)      

  157.    {      

  158.       

  159.             throw new IllegalArgumentException("The scale must be a positive integer or zero");      

  160.       

  161.             }      

  162.       

  163.         BigDecimal b = new BigDecimal(Double.toString(v));      

  164.       

  165.         BigDecimal one = new BigDecimal("1");      

  166.       

  167.         return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();      

  168.       

  169.     }      

  170.       

  171.       

  172. }       














评论也很精彩,请点击查看精彩评论。欢迎您也添加评论。查看详细 >>





JavaEye推荐
北京:优秀公司NHNChina招聘:WEB开发,系统管理,JAVA开发, DBA
广州:急招 JAVA开发经理/系统架构师(10-15K/月)也招聘java程序员
与Hibernate之父面对面-4月19日 Gavin King上海交流研讨会
高薪工作机会 美国法国上海 15-20k/月 J2EE SA



文章来源: http://xiaozhe.javaeye.com/blog/71871
posted on 2007-04-17 15:18 xiaozhe 阅读(1781) 评论(3)  编辑  收藏

FeedBack:
# re: [导入]java实现double的精确计算和四舍五入 2011-05-11 14:37 tt
public double round(double value){



return Math.round(value*100)/100.0;



}

-----------------------------
够笨的,换成*1000/1000.0看看  回复  更多评论
  
# re: [导入]java实现double的精确计算和四舍五入 2011-09-27 11:56 wxy
10325.55*0.3兄弟试一下这个  回复  更多评论
  
# re: [导入]java实现double的精确计算和四舍五入 2011-09-27 11:56 wxy
10325.55*0.3兄弟试下这个  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: