从之前的浮点数运算 中我们知道,浮点数运算会使结果不精确,且存储值越大,损失的精度也就越大。在通常情况下,long与double类型已经可以满足我们的要求了,但是对于一些要求精确计算结果的行业(如银行)来说,误差就太大了。
幸运的是,Java提供了BigInteger与BigDecimal两个类,使用这两个类可以处理任意精度的数值,这两个类位于java.math包 中。其中BigInteger可以对任意精度的整数进行运算,BigDecial可以对任意精度的小数进行运算。BigDecimal的构造器有很多,但 是常用的是带String参数的构造器:public BigDecimal(String val),建议不要使用带double参数的构造器:public BigDecimal(double val),因为double参数的构造器是不精确的,下例可以说明这个问题。
public class ConstructorTest {
public static void main(String[] args) {
BigDecimal bstring=new BigDecimal(“0.7″);
BigDecimal bdouble=new BigDecimal(0.7);
System.out.println(“String参数结果:”+bstring);
System.out.println(“double参数结果:”+bdouble);
}
}
输出结果:
String参数结果:0.7
double参数结果:0.6999999999999999555910790149937383830547332763671875
显然,String参数的构造器是准确的,而double参数的构造器只是输出了近似的结果,因为是以double类型传入0.7的时候,0.7在计算机中不能精确地表示出来。
现在我们来看看这两个类的使用,这里只是简单的演示,要了解更详细的信息,可以查阅javaAPI文档。
public class BigNumberTest{
public static void main(String[] args) {
//BigInteger的运算
BigInteger bi1=new BigInteger(“12345678901234567890″);
BigInteger bi2=new BigInteger(“98765432109876543210″);
System.out.println(“*******BigInteger的运算*********”);
System.out.println(“bi1+bi2=”+bi1.add(bi2));
System.out.println(“bi1-bi2=”+bi1.subtract(bi2));
System.out.println(“bi1*bi2=”+bi1.multiply(bi2));
System.out.println(“bi1/bi2=”+bi1.divide(bi2));
System.out.println(“bi1%bi2=”+bi1.remainder(bi2));
//BigDecimal的运算
BigDecimal bd1=new BigDecima(“1.23456789012345678901″);
BigDecimal bd2=new BigDecima(“9.87654321098765432109″);
System.out.println(“********BigDecimal的运算*******”);
System.out.println(“bd1+bd2=”+bd1.add(bd2));
System.out.println(“bd1-bd2=”+bd1.subtract(bd2));
System.out.println(“bd1*bd2=”+bd1.multiply(bd2));
//System.out.println(“bd1/bd2=”+bd1.divide(bd2));
System.out.println(“bd1/bd2=”+bd1.divide(bd2,MathContext.DECIMAL128));
System.out.println(“bd1%bd2=”+bd1.remainder(bd2));
}
}
运行结果:
*********BigInteger的运算*********
bi1+bi2=111111111011111111100
bi1-bi2=-86419753208641975320
bi1*bi2=1219326311370217952237463801111263526900
bi1/bi2=0
bi1%bi2=12345678901234567890
*********BigDecimal的运算*********
bd1+bd2=11.11111110111111111010
bd1-bd2=-8.64197532086419753208
bd1*bd2=12.1932631137021795225845145533336229232209
bd1/bd2=0.1249999988609375000141117187602160
bd1%bd2=1.23456789012345678901
可以看出,尽管在程序中指定了相当大的整数和小数,但结果依然没有精度丢失。但是这种计算方式也给编程带来了额外的工作量,运行速度也远不及基本数据类型,所以要谨慎使用。
上面程序标为注释的一行中,BigDecimal类中的方法:public BigDecimal divide(BigDecimal divisor)如果因为存在无穷的十进制扩展(如10除以7的商值)导致无法准确表示商值得结果,则抛出ArithmeticException。而上 面程序标为注释的一行就是一个无穷小数,就会抛出异常。所以这里采用的重载的方法:
public BigDecimal divide(BigDecimal divisor,MathContext mc)其中mc参数指定对商的舍入模式,程序中采用精度较高的IEEE 754R BigDecimal128模式。
我们要对数据进行精确的计算时,还是要看情况来选择使用什么类型来确保结果的准确性,一般考虑使用long类型来取代浮点类型,来确保结果的准确性,必要 时可使用BigInteger与BigDecimal,但是这两个类的性能消耗较大,得看具体情况谨慎使用。本文转载来自八零客团队博客 ,80客 团队成员的文章http://www.balingke.com/archives/741.html
BigInteger与BigDecimal
最新推荐文章于 2024-11-11 00:03:55 发布