java BigDecimal

BigDecimal类:双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。下面列出了BigDecimal类的主要构造器和方法:

构造器描述:

  BigDecimal(int)创建一个具有参数所指定整数值的对象。

  BigDecimal(double)创建一个具有参数所指定双精度值的对象。

  BigDecimal(long)创建一个具有参数所指定长整数值的对象。

  BigDecimal(String)创建一个具有参数所指定以字符串表示的数值的对象。

方法描述:

  add(BigDecimal)BigDecimal对象中的值相加,然后返回这个对象。

  subtract(BigDecimal)BigDecimal对象中的值相减,然后返回这个对象。

  multiply(BigDecimal)BigDecimal对象中的值相乘,然后返回这个对象。

  divide(BigDecimal)BigDecimal对象中的值相除,然后返回这个对象。
  
  pow(int n)BigDecimal对象中的值乘幂,然后返回这个对象。

  toString()将BigDecimal对象的数值转换成字符串。

  doubleValue()将BigDecimal对象中的值以双精度数返回。

  floatValue()将BigDecimal对象中的值以单精度数返回。

  longValue()将BigDecimal对象中的值以长整数返回。

  intValue()将BigDecimal对象中的值以整数返回。
  
  valueOf()将float,double类型转换为BigDecimal

注意,由于一般数值类型,例如double,不能准确地代表16位有效数以上的数字,在使用BigDecimal时,应用BigDecimal(String)构造器创建对象才有意义。另外,BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。

下面是BigDecimal的一些常用例子:

   //创建BigDecimal对象 
  BigDecimal bigNumber = new BigDecimal("89.1234567890123456789"); 
  BigDecimal bigRate = new BigDecimal(1000); 
  BigDecimal bigResult = new BigDecimal(); //对象bigResult的值为0.0 
  
  //对bigNumber的值乘以1000,结果赋予bigResult 
  bigResult = bigNumber.multiply(bigRate); 
  System.out.println(bigResult.toString()); 
  //或者System.out.println(bigResult); 
  //显示结果:89123.4567890123456789000
   
  //以双精度数返回bigNumber中的值 
  double dData = bigNumber.doubleValue(); 
  System.out.println(dData); //结果:89.12345678901235 

注意使用方法doubleValue()将对象bigNumber中的值以双精度数值返回时,将丢失数据的准确性。使用其他方法,如xxxValue()时均存在这个问题,使用时必须慎重。

BigDecimal用来对超过16有效位以上的数值进行运算和操作。所有的算术运算都通过调用其相应的方法进行。创建一个超过16有效位数的对象时,运用BigDecimal(String)才可避免丢失数字的精确度。


BigDecimal和格式化:

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

java四舍五入:

import java.math.BigDecimal; //引入这个包 

public class Test { 
public static void main(String[] args) { 

   double i = 3.856; 

   // 舍掉小数取整 
   System.out.println("舍掉小数取整:Math.floor(3.856)=" + (int) Math.floor(i)); 

   // 四舍五入取整 
   System.out.println("四舍五入取整:(3.856)=" 
     + new BigDecimal(i).setScale(0, BigDecimal.ROUND_HALF_UP)); 

   // 四舍五入保留两位小数 
   System.out.println("四舍五入保留两位小数:(3.856)=" 
     + new BigDecimal(i).setScale(2, BigDecimal.ROUND_HALF_UP)); 

   // 凑整,取上限 
   System.out.println("凑整:Math.ceil(3.856)=" + (int) Math.ceil(i)); 

   // 舍掉小数取整 
   System.out.println("舍掉小数取整:Math.floor(-3.856)=" + (int) Math.floor(-i)); 
   // 四舍五入取整 
   System.out.println("四舍五入取整:(-3.856)=" 
     + new BigDecimal(-i).setScale(0, BigDecimal.ROUND_HALF_UP)); 

   // 四舍五入保留两位小数 
   System.out.println("四舍五入保留两位小数:(-3.856)=" 
     + new BigDecimal(-i).setScale(2, BigDecimal.ROUND_HALF_UP)); 

   // 凑整,取上限 
   System.out.println("凑整(-3.856)=" + (int) Math.ceil(-i)); 

输出结果:

舍掉小数取整:Math.floor(3.856)=3
四舍五入取整:(3.856)=4
四舍五入保留两位小数:(3.856)=3.86
凑整:Math.ceil(3.856)=4
舍掉小数取整:Math.floor(-3.856)=-4
四舍五入取整:(-3.856)=-4
四舍五入保留两位小数:(-3.856)=-3.86
凑整(-3.856)=-3

关于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

setScale(1,BigDecimal.ROUND_HALF_DOWN)五舍六入,2.35变成2.3,2.36变成2.4


测试代码:

1.测试参数类型为double和String的两个常用构造函数。

BigDecimal aDouble =new BigDecimal(1.22);
System.out.println("construct with a double value: " + aDouble);
BigDecimal aString = new BigDecimal("1.22");
System.out.println("construct with a String value: " + aString);

输出结果如下:
construct with a double value:1.2199999999999999733546474089962430298328399658203125
construct with a String value: 1.22

(1)参数类型为double的构造方法的结果有一定的不可预知性。
(2)String 构造方法是完全可预知的:写入 newBigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用String构造方法。
(3)当double必须用作BigDecimal的源时,请使用static valueOf(double)方法。

valueOf源码:

public   static BigDecimal valueOf(double val) {

       return new BigDecimal(Double.toString(val));

}

2.测试加法操作。

BigDecimal a =new BigDecimal("1.22");
System.out.println("construct with a String value: " + a);
BigDecimal b =new BigDecimal("2.22");
a.add(b);
System.out.println("a plus b is : " + a);

输出结果:a plus b is : 1.22

因为BigDecimal是不可变的(immutable),在进行每一步运算时,都会产生一个新的对象,所以a.add(b);虽然做了加法操作,但是a并没有保存加操作后的值,正确的用法应该是a=a.add(b);

3.测试除法操作。

BigDecimal total1 = new BigDecimal(200).setScale(3, BigDecimal.ROUND_HALF_UP);
//表示这个total1的初始值为200.000

BigDecimal total2 = new BigDecimal(10).setScale(3, BigDecimal.ROUND_HALF_UP);
//表示这个total2的初始值为10.000

total1.divide(total2);

会报错:
Non-terminating decimal expansion; no exact representable decimal result

正确的方法:
total1.divide(total2,3,BigDecimal.ROUND_HALF_UP);
这样才不会报错,你必须为它保留小数位。


总结:

  1. 商业计算使用BigDecimal。
  2. 尽量使用参数类型为String的构造函数。
  3. BigDecimal是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要保存操作后的值。
  4. 我们往往容易忽略JDK底层的一些实现细节,导致出现错误,需要多加注意。

参考:
http://oracle-9i.iteye.com/blog/1103316
http://blog.csdn.net/jackiehff/article/details/8582449

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值