BigDecimal

java的float只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。

在使用BigDecimal类来进行计算的时候,主要分为以下步骤:

             1、用float或者double变量构建BigDecimal对象。

             2、通过调用BigDecimal的加,减,乘,除等相应的方法进行算术运算。

             3、把BigDecimal对象转换成float,double,int等类型。

 

Bigdecimal是无法直接用+-*/这些符号进行计算的,它有自己的运算方法,如下;
 
public BigDecimal add(BigDecimal value);           //加法
public BigDecimal subtract(BigDecimal value);      //减法 
public BigDecimal multiply(BigDecimal value);      //乘法
public BigDecimal divide(BigDecimal value);        //除法


可以使用BigDecimal的构造方法或者静态方法的valueOf()方法把基本类型的变量构建成BigDecimal对象。
BigDecimal一共有4个构造方法
BigDecimal(int) 创建一个具有参数所指定整数值的对象。
BigDecimal(double) 创建一个具有参数所指定双精度值的对象。
BigDecimal(long) 创建一个具有参数所指定长整数值的对象。
BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象
BigDecimal b2 = BigDecimal.valueOf(0.48);

toString()             将BigDecimal对象的数值转换成字符串。
doubleValue()          将BigDecimal对象中的值以双精度数返回。
floatValue()           将BigDecimal对象中的值以单精度数返回。
longValue()            将BigDecimal对象中的值以长整数返回。
intValue()             将BigDecimal对象中的值以整数返回。
 
 进行相应的计算后,我们可能需要将BigDecimal对象转换成相应的基本数据类型的变量,可以使用floatValue(),doubleValue()等方法。
 
可以在运算前后对其进行精度的设置:如下文:
BigDecimal.setScale()方法用于格式化小数点
setScale(1)表示保留一位小数,默认用四舍五入方式 
setScale(1,BigDecimal.ROUND_DOWN)直接删除多余的小数位,如2.35会变成2.3 
setScale(1,BigDecimal.ROUND_UP)进位处理,2.35变成2.4 
setScale(1,BigDecimal.ROUND_HALF_UP)四舍五入,2.35变成2.4        适用元角分模式
setScaler(1,BigDecimal.ROUND_HALF_DOWN)四舍五入,2.35变成2.3,如果是5则向下舍
 
 
注释:
1:scale指的是你小数点后的位数。比如123.456则score就是3.
score()就是BigDecimal类中的方法啊。
比如:BigDecimal b = new BigDecimal("123.456");
b.scale(),返回的就是3.
 
2:roundingMode是小数的保留模式。它们都是BigDecimal中的常量字段,有很多种。
比如:BigDecimal.ROUND_HALF_UP表示的就是4舍5入。

3:pubilc BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
的意思是说:我用一个BigDecimal对象除以divisor后的结果,并且要求这个结果保留有scale个小数位,roundingMode表示的就是保留模式是什么,是四舍五入啊还是其它的,你可以自己选!
 

4:对于一般add、subtract、multiply方法的小数位格式化如下:

BigDecimal mData = new BigDecimal("9.655").setScale(2, BigDecimal.ROUND_HALF_UP);
        System.out.println("mData=" + mData);
 
----结果:----- mData=9.66
 
========================================================================================
 
精度设置,为什么会设置精度,给大家看个效果
 
BigDecimal abig=new BigDecimal(10.0);  

BigDecimal bbig=new BigDecimal(9.1);  

BigDecimal cbig=new BigDecimal(8.9);  

System.out.println(abig.subtract(bbig));  

System.out.println(abig.subtract(cbig));  

结果如下:

0.9000000000000003552713678800500929355621337890625  

1.0999999999999996447286321199499070644378662109375  
 
并不是我们希望看到的0.9和1.1,原因就是转成二进制的时候会有精度问题,导致这样的结果。所以我们可以在运算的时候加精度,也可以在实例化BigDecimal的时候用字符串。
 
设置精度的方法:

System.out.println(abig.subtract(bbig).setScale(2, BigDecimal.ROUND_HALF_UP));  

System.out.println(abig.subtract(cbig).setScale(2, BigDecimal.ROUND_HALF_UP));  
这样设置两位精度就可以啦
0.90  

1.10  
 
取反

因为Bigdecimal是无法直接用+-*/这些符号进行计算的,所以取反的时候也需要一个单独的方法来实现:

System.out.println(abig.negate());  

这样就会拿到它的相反数了:

-10.0 

========================================================================================
 以下是一个工具类,该工具类提供加,减,乘,除运算。转自:http://www.cnblogs.com/chenssy/archive/2012/09/09/2677279.html
public class Arith {
    /**
     * 提供精确加法计算的add方法
     * @param value1 被加数
     * @param value2 加数
     * @return 两个参数的和
     */
    public static double add(double value1,double value2){
        BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
        BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
        return b1.add(b2).doubleValue();
    }
    
    /**
     * 提供精确减法运算的sub方法
     * @param value1 被减数
     * @param value2 减数
     * @return 两个参数的差
     */
    public static double sub(double value1,double value2){
        BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
        BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
        return b1.subtract(b2).doubleValue();
    }
    
    /**
     * 提供精确乘法运算的mul方法
     * @param value1 被乘数
     * @param value2 乘数
     * @return 两个参数的积
     */
    public static double mul(double value1,double value2){
        BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
        BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
        return b1.multiply(b2).doubleValue();
    }
    
    /**
     * 提供精确的除法运算方法div
     * @param value1 被除数
     * @param value2 除数
     * @param scale 精确范围
     * @return 两个参数的商
     * @throws IllegalAccessException
     */
    public static double div(double value1,double value2,int scale) throws IllegalAccessException{
        //如果精确范围小于0,抛出异常信息
        if(scale<0){         
            throw new IllegalAccessException("精确度不能小于0");
        }
        BigDecimal b1 = new BigDecimal(Double.valueOf(value1));
        BigDecimal b2 = new BigDecimal(Double.valueOf(value2));
        return b1.divide(b2, scale).doubleValue();    
    }
}

 

格式化及例子
由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。

以利用BigDecimal对货币和百分比格式化为例。首先,创建BigDecimal对象,进行BigDecimal的算术运算后,分别建立对货币和百分比格式化的引用,最后利用BigDecimal对象作为format()方法的参数,输出其格式化的货币值和百分比。

 

public static void main(String[] args) {  

    NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立货币格式化引用   

    NumberFormat percent = NumberFormat.getPercentInstance();  //建立百分比格式化引用   

    percent.setMaximumFractionDigits(3); //百分比小数点最多3位   

    BigDecimal loanAmount = new BigDecimal("15000.48"); //贷款金额  

    BigDecimal interestRate = new BigDecimal("0.008"); //利率     

    BigDecimal interest = loanAmount.multiply(interestRate); //相乘  

    System.out.println("贷款金额:\t" + currency.format(loanAmount));   

    System.out.println("利率:\t" + percent.format(interestRate));   

    System.out.println("利息:\t" + currency.format(interest));   
}


运行结果如下:

贷款金额:    ¥15,000.48  

利率:    0.8%  

利息:    ¥120.00  

 


BigDecimal比较
BigDecimal是通过使用compareTo(BigDecimal)来比较的,具体比较情况如下:

public static void main(String[] args) {  

    BigDecimal a = new BigDecimal("1");  

    BigDecimal b = new BigDecimal("2");  

    BigDecimal c = new BigDecimal("1");  

    int result1 = a.compareTo(b);  

    int result2 = a.compareTo(c);  

    int result3 = b.compareTo(a);  

    System.out.println(result1);  

    System.out.println(result2);  

    System.out.println(result3);  

}  

打印结果是:-101,即左边比右边数大,返回1,相等返回0,比右边小返回-1
 
注意不能使用equals方法来比较大小。

使用BigDecimal的坏处是性能比double和float差,在处理庞大,复杂的运算时尤为明显,因根据实际需求决定使用哪种类型。

 

Creating a NumberFormat

Creating a NumberFormat for a specific Locale is done like this:

Locale locale = new Locale("da", "DK");

NumberFormat numberFormat = NumberFormat.getInstance(locale);

和Locale  一起用会格式化一些国家的金额。

详细API :http://tutorials.jenkov.com/java-internationalization/numberformat.html

 

 
posted @ 2017-03-01 19:06  xh_Blog  阅读(449)  评论(0编辑  收藏  举报