Java数字计算:使用BigInteger与BigDecimal

因为Java(大部分程式语言都是)是使用IEEE754演算标準,小数计算会有误差,所以需要精确的做四则运算,需用更适用的类别来处理。

BigInteger

在Java中整数的最大值为9223372036854775807,最小值是-9223372036854775808,如果要表示超过这个範围的数字,就要使用BigInteger类别。

因为数字已经大于int及long的範围了,所以传入BigInteger中时会使用String

BigInteger n = new BigInteger("9223372036854775808");

四则运算则要用add、subtract、multiply、divide等(有BigInteger.ONE、BigInteger.TEN等保留字)

BigInteger n1 = new BigInteger("9223372036854775808");BigInteger n2 = new BigInteger("9223372036854775809");n.add(n2);n.subtract(n2);n.multiply(n2);n.divide(n2);

两数比较则可以用equals()与compareTo()

BigInteger n1 = new BigInteger("200");BigInteger n2 = new BigInteger("100");n1.compareTo(n2);//相等回传0,n1>n2回传1,n1<n2回传-1n1.equals(n2);//等于回传true,否则回传false

BigInteger与基本型态之间的转换

n1.longValue(); //转为longn1.intValue();  //转为intBigInteger.valueOf(100); //由int转为BigInteger

如果由BigInteger转回基本型态的数字超过基本型态可以容纳的範围,会使数字失去精度,此时就可以使用intValueExtract()、longValueExtract()等,使之抛出例外。

BigInteger n1 = new BigInteger("3333333333333333333333333");n1.intValueExact();//会抛出 java.lang.ArithmeticException例外

一般于Math类别常用的方法BigInteger也皆有支援(sqrt除外)

BigInteger n1 = new BigInteger("200");BigInteger n2 = new BigInteger("100");n1.pow(2);n1.abs();n1.min(n2);n1.max(n2);

BigDecimal

与BigInteger方法大同小异,可以防止小数计算时因IEEE754规範所造成的误差。
比较特别的是四捨五入、无条件捨去、无条件进入的处理
先提一下Math类别的处理:

Math.round(5.4);    //四捨五入Math.ceil(5.4);     //无条件进位Math.floor(5.4);    //无条件捨去

要注意,无条件进位是往数字大的方向进位,无条件捨去是往数字小的方向捨去
而此种进位方式如果牵扯到小数,有可能会因为IEEE754标準而发生误差。
举例:-5.5用Math.round()四捨五入的结果会是-5
此时就可以使用BigDecimal的进位方式:

BigDecimal r = new BigDecimal(-3.3456789); BigDecimal i1 = r.setScale(3,RoundingMode.UP);BigDecimal i2 = r.setScale(3,RoundingMode.DOWN);BigDecimal i3 = r.setScale(3,RoundingMode.CEILING);BigDecimal i4 = r.setScale(3,RoundingMode.FLOOR);BigDecimal i5 = r.setScale(3,RoundingMode.HALF_UP);BigDecimal i6 = r.setScale(3,RoundingMode.HALF_DOWN);BigDecimal i7 = r.setScale(3,RoundingMode.HALF_EVEN);
UP:往该数绝对值大的方向进位DOWN:往该数绝对值小的方向捨去CEILING:与Math.ceil的进位方式相同FLOOR:与Math.floor的进位方式相同HALF_UP:四捨五入(不会有误差)HALF_DOWN:五捨去,六以上进位HALF_EVEN:银行家捨入法

而BigDecimal可以用setScale来设定量级
r.setScale(3,RoundingMode.HALF_UP):这就代表四捨五入到小数点后第三位

比较一下其余可能影响进位的类别

DecimalFormat(还是会有IEEE754所造成的精準度问题):比较常用在格式化数字
DecimalFormat df = new DecimalFormat("#.00");System.out.println(df.format(-3.155));
String.format:会无条件捨去
double d = -3.146;String result = String.format("%.2f",d);System.out.println(result);

关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章