Java Bigdecimal使用原理详解
一般来说,一提到Java里面的商业计算,我们都知道不能用float和double,因为他们无法进行精确计算。但是Java的设计者给编程人员提供了一个很有用的类BigDecimal,他可以完善float和double类无法进行精确计算的缺憾。
BigDecimal类位于java.maths类包下。首先我们来看下如何构造一个BigDecimal对象。它的构造函数很多,这里挑选最常用的两个来演示一下:一个就是BigDecimal(doubleval),另一个就是BigDecimal(Stringstr)。这两个看上去没什么太大区别,但是正像API描述中说:
/*Theresultsofthisconstructorcanbesomewhatunpredictable.Onemightassumethat
newBigDecimal(.1)isexactlyequalto.1,butitisactuallyequal
to.1000000000000000055511151231257827021181583404541015625.Thisissobecause.1
cannotberepresentedexactlyasadouble(or,forthatmatter,asabinaryfraction
ofanyfinitelength).Thus,thelongvaluethatisbeingpassedintotheconstructor
isnotexactlyequalto.1,appearancesnonwithstanding.
The(String)constructor,ontheotherhand,isperfectlypredictable:newBigDecimal
(".1")isexactlyequalto.1,asonewouldexpect.Therefore,itisgenerally
recommendedthatthe(String)constructorbeusedinpreferencetothisone.*/
也就是说利用double作为参数的构造函数,无法精确构造一个BigDecimal对象,需要自己指定一个上下文的环境,也就是指定精确位。而利用String对象作为参数传入的构造函数能精确的构造出一个BigDecimal对象。请看下面的代码:
importjava.math.*; publicclassTestBigDecimal{ publicstaticvoidmain(Stringargs[]){ BigDecimalbd=newBigDecimal("10.123"); BigDecimalbd1=newBigDecimal(10.123); System.out.println(bd+"/n"+bd1); } } 运行后输出: 10.123 10.1229999999999993320898283855058252811431884765625
所以我们在选择构造函数时,要看具体需求而定。
另外,很多人会问到怎么将基本类型,如int,float,double,long,和BigDecimal对象相互转换。很简单:
基本类型通过构造函数转换成对应的BigDecimal对象,而BigDecimal类提供了诸如intValue(),floatValue(),doubleValue(),longValue()方法来将BigDecimal对象转换成对应的值。
一、BigDecimal的加减乘除
BigDecimalbignum1=newBigDecimal("10"); BigDecimalbignum2=newBigDecimal("5"); BigDecimalbignum3=null; //加法 bignum3=bignum1.add(bignum2); System.out.println("和是:"+bignum3); //减法 bignum3=bignum1.subtract(bignum2); System.out.println("差是:"+bignum3); //乘法 bignum3=bignum1.multiply(bignum2); System.out.println("积是:"+bignum3); //除法 bignum3=bignum1.divide(bignum2); System.out.println("商是:"+bignum3);
二、BigDecimal的比较大小。
BigDecimalnum1=newBigDecimal("0"); BigDecimalnum2=newBigDecimal("1"); BigDecimalnum3=newBigDecimal("2"); BigDecimalnum=newBigDecimal("1");//用做比较的值 System.out.println(num1.compareTo(num));//小于时,返回-1 System.out.println(num2.compareTo(num));//等于时,返回0 System.out.println(num3.compareTo(num));//大于时,返回1
补充:
BigInteger也可以存放比较大的数,和BigDecimal的区别是:BigInteger存放的是大的整数,而BigDecimal存放大的小数
继续补充一下,用BigDecimal写个for循环。
for(BigDecimali=newBigDecimal("0");i.compareTo(newBigDecimal("10"))!=1;i=i.add(newBigDecimal("1"))){ System.out.print(i+"\t"); }
控制台打印的是从0到10。
三、Java中的BigDecimal使用注意事项
1.BigDecial是immutable的,就像String一样,它的所有操作都会生成一个新的对象,所以
amount.add(thisAmount);
是错误的;而应该是:
amount=amount.add(thisAmount);
2.不要用equals方法来比较BigDecimal对象,因为它的equals方法会比较scale,如果scale不一样,它会返回false;
BigDecimala=newBigDecimal("2.00");
BigDecimalb=newBigDecimal("2.0");
print(a.equals(b));//false
所以你应该使用compareTo()和signum()方法
a.compareTo(b);//returns(-1ifab)
a.signum();//returns(-1ifa<0),(0ifa==0),(1ifa>0)
3.使用BigDecimal的字符串构造函数,不要使用double参数的构造函数,否则的话会出现你不想要的结果。
例如下面的代码分别使用double和String的构造函数,然后使用HALF_EVEN的round方法,但是输出结果不一样
System.out.println("=================="); for(inti=0;i<10;i++){ StringBuffersb=newStringBuffer(); sb.append("0."); sb.append(i); sb.append("5"); BigDecimalbdx=newBigDecimal(sb.toString()); System.out.println(sb+""+bdx.setScale(1,RoundingMode.HALF_EVEN)); } System.out.println("=================="); for(inti=0;i<10;i++){ StringBuffersb=newStringBuffer(); sb.append("0."); sb.append(i); sb.append("5"); BigDecimalbdx=newBigDecimal(Double.valueOf(sb.toString())); System.out.println(sb+""+bdx.setScale(1,RoundingMode.HALF_EVEN)); }
输出是:
==================
0.050.0
0.150.2
0.250.2
0.350.4
0.450.4
0.550.6
0.650.6
0.750.8
0.850.8
0.951.0
==================
0.050.1
0.150.1
0.250.2
0.350.3
0.450.5
0.550.6
0.650.7
0.750.8
0.850.8
0.950.9
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。