因为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);