java实现double的精确计算和四舍五入

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

 

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.   
  3. public class Arith         
  4.   
  5. {         
  6.   
  7.  private static final int DEF_DIV_SCALE = 10;         
  8.   
  9.          
  10.   
  11.    private Arith()         
  12.   
  13.    {         
  14.   
  15.          
  16.   
  17.       }         
  18.   
  19.          
  20.   
  21.          
  22.   
  23.     /**      
  24.  
  25.       
  26.  
  27.      * 提供精确的加法运算。      
  28.  
  29.       
  30.  
  31.      * @param v1 被加数      
  32.  
  33.       
  34.  
  35.      * @param v2 加数      
  36.  
  37.       
  38.  
  39.      * @return 两个参数的和      
  40.  
  41.       
  42.  
  43.      */         
  44.   
  45.          
  46.   
  47.     public static double add(double v1,double v2)         
  48.   
  49.    {         
  50.   
  51.          
  52.   
  53.         BigDecimal b1 = new BigDecimal(Double.toString(v1));         
  54.   
  55.          
  56.   
  57.         BigDecimal b2 = new BigDecimal(Double.toString(v2));         
  58.   
  59.          
  60.   
  61.         return b1.add(b2).doubleValue();         
  62.   
  63.          
  64.   
  65.         }         
  66.   
  67.          
  68.   
  69.    /**      
  70.  
  71.       
  72.  
  73.      * 提供精确的减法运算。      
  74.  
  75.       
  76.  
  77.      * @param v1 被减数      
  78.  
  79.       
  80.  
  81.      * @param v2 减数      
  82.  
  83.       
  84.  
  85.      * @return 两个参数的差      
  86.  
  87.       
  88.  
  89.      */         
  90.   
  91.          
  92.   
  93.     public static double sub(double v1,double v2)         
  94.   
  95.    {         
  96.   
  97.          
  98.   
  99.         BigDecimal b1 = new BigDecimal(Double.toString(v1));         
  100.   
  101.          
  102.   
  103.         BigDecimal b2 = new BigDecimal(Double.toString(v2));         
  104.   
  105.          
  106.   
  107.         return b1.subtract(b2).doubleValue();         
  108.   
  109.          
  110.   
  111.      }         
  112.   
  113.          
  114.   
  115.          
  116.   
  117.   /**      
  118.  
  119.       
  120.  
  121.      * 提供精确的乘法运算。      
  122.  
  123.       
  124.  
  125.      * @param v1 被乘数      
  126.  
  127.       
  128.  
  129.      * @param v2 乘数      
  130.  
  131.       
  132.  
  133.      * @return 两个参数的积      
  134.  
  135.       
  136.  
  137.      */         
  138.   
  139.          
  140.   
  141.     public static double mul(double v1,double v2)         
  142.   
  143.   {         
  144.   
  145.          
  146.   
  147.   BigDecimal b1 = new BigDecimal(Double.toString(v1));         
  148.   
  149.          
  150.   
  151.   BigDecimal b2 = new BigDecimal(Double.toString(v2));         
  152.   
  153.          
  154.   
  155.   return b1.multiply(b2).doubleValue();         
  156.   
  157.          
  158.   
  159.   }         
  160.   
  161.          
  162.   
  163.           
  164.   
  165.   /**      
  166.  
  167.       
  168.  
  169.      * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到      
  170.  
  171.       
  172.  
  173.      * 小数点以后10位,以后的数字四舍五入。      
  174.  
  175.       
  176.  
  177.      * @param v1 被除数      
  178.  
  179.       
  180.  
  181.      * @param v2 除数      
  182.  
  183.       
  184.  
  185.      * @return 两个参数的商      
  186.  
  187.       
  188.  
  189.      */         
  190.   
  191.          
  192.   
  193.     public static double div(double v1,double v2)         
  194.   
  195.   {         
  196.   
  197.          
  198.   
  199.         return div(v1,v2,DEF_DIV_SCALE);         
  200.   
  201.          
  202.   
  203.         }         
  204.   
  205.          
  206.   
  207.           
  208.   
  209.          
  210.   
  211.    /**      
  212.  
  213.       
  214.  
  215.      * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指      
  216.  
  217.       
  218.  
  219.      * 定精度,以后的数字四舍五入。      
  220.  
  221.       
  222.  
  223.      * @param v1 被除数      
  224.  
  225.       
  226.  
  227.      * @param v2 除数      
  228.  
  229.       
  230.  
  231.      * @param scale 表示表示需要精确到小数点以后几位。      
  232.  
  233.       
  234.  
  235.      * @return 两个参数的商      
  236.  
  237.       
  238.  
  239.      */         
  240.   
  241.          
  242.   
  243.     public static double div(double v1,double v2,int scale)         
  244.   
  245.   {         
  246.   
  247.          
  248.   
  249.    if(scale<0)         
  250.   
  251.     {         
  252.   
  253.          
  254.   
  255.     throw new IllegalArgumentException("The scale must be a positive integer or zero");         
  256.   
  257.          
  258.   
  259.       }         
  260.   
  261.          
  262.   
  263.         BigDecimal b1 = new BigDecimal(Double.toString(v1));         
  264.   
  265.          
  266.   
  267.         BigDecimal b2 = new BigDecimal(Double.toString(v2));         
  268.   
  269.          
  270.   
  271.         return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();         
  272.   
  273.          
  274.   
  275.      }         
  276.   
  277.          
  278.   
  279.           
  280.   
  281.          
  282.   
  283.    /**      
  284.  
  285.       
  286.  
  287.      * 提供精确的小数位四舍五入处理。      
  288.  
  289.       
  290.  
  291.      * @param v 需要四舍五入的数字      
  292.  
  293.       
  294.  
  295.      * @param scale 小数点后保留几位      
  296.  
  297.       
  298.  
  299.      * @return 四舍五入后的结果      
  300.  
  301.       
  302.  
  303.      */         
  304.   
  305.          
  306.   
  307.     public static double round(double v,int scale){         
  308.   
  309.          
  310.   
  311.         if(scale<0)         
  312.   
  313.    {         
  314.   
  315.          
  316.   
  317.             throw new IllegalArgumentException("The scale must be a positive integer or zero");         
  318.   
  319.          
  320.   
  321.             }         
  322.   
  323.          
  324.   
  325.         BigDecimal b = new BigDecimal(Double.toString(v));         
  326.   
  327.          
  328.   
  329.         BigDecimal one = new BigDecimal("1");         
  330.   
  331.          
  332.   
  333.         return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();         
  334.   
  335.          
  336.   
  337.     }         
  338.   
  339.          
  340.   
  341. }          
import java.math.BigDecimal;       public class Arith       {        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();                  }              }       
           

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow
这里写图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值