本篇主要介绍的是我们在日常开发中经常用到的JDK对象,这里进行了一些分类性总结和差异比较。由于这里涉及的很多工具类都是大家耳熟能详的,因此不会长篇大论的介绍每一个概念和细节,我们还是继续秉承该系列的风格,通过更多实用的可执行的示例代码和关键性注释来阐述他们的功能和技术细节,让我们现在就开始吧。
大数值对象(BigDecimal)
和普通的原始类型相比,该类主要提供以下几点优势:
①可以表示任意大十进制数值;
② 提供了基本的数学函数,同时也支持各种数学运算符;
③ 提供了与字符串(String)和原始数值类型之间的各种转换;
④ 与double和Double相比,在进行浮点运算时不丢失精度;
⑤ 提供可靠的四舍五入表示。
那么的劣势又是什么呢?性能!因此如果我们的系统需要进行大量的科学计算,那么BigDecimal将不是一个很好的选择,特别是对那些高密度计算的程序,在这种情况下我们的首选还是原始数据类型。因此BigDecimal更适用于基于商业规则的运算程序,如保单和利息等。
下面将给出几个比较典型的应用示例:
① BigDecimal与String和任意数值类型的转换:
1 public static void main(String args[]) { 2 BigDecimal bd1 = new BigDecimal("123456789.0123456890"); 3 BigDecimal bd2 = BigDecimal.valueOf(123L); 4 bd1 = bd1.add(bd2); 5 System.out.println(bd2.toPlainString()); 6 BigDecimal bd3 = new BigDecimal(bd2.toPlainString()); 7 if (bd3.equals(bd2)) 8 System.out.println("bd2 is equal to bd3"); 9 if (bd2.intValue() == 123)10 System.out.println("bd2 is equal to 123.");11 }12 /* 输出结果如下:13 12314 bd2 is equal to bd315 bd2 is equal to 123.16 */
由上例的输出结果可见,BigDecimal中提供了各种类型之间的可传递性转换,既上例中的bd2对象,源于123L,然后再将该对象转换会原始类型时,得到的值和之前初始化该对象的值仍然是相等的。上例中还用将bd2转换为字符串,并用该结果构造了另外一个BigDecimal对象,在比较这个两个对象的值时,发现他们是相等的。这种可传递性的类型之间的转换,Effective Java的作者是比较推崇的。
② 基本的数学运算和数学函数应用:
1 public static void main(String args[]) {
2 BigDecimal bd1 = new BigDecimal("123456789.0123456890");
3 BigDecimal bd2 = BigDecimal.valueOf(123L);
4 bd1 = bd1.add(bd2);
5 System.out.printf("bd1 = %s after add. ",bd1.toPlainString());
6 bd1 = bd1.multiply(bd2);
7 System.out.printf("bd1 = %s after multiply. ",bd1.toPlainString());
8 bd1 = bd1.subtract(bd2);
9 System.out.printf("bd1 = %s after subtract. ",bd1.toPlainString());
10 bd1 = bd1.divide(bd2, BigDecimal.ROUND_UP);
11 System.out.printf("bd1 = %s after divide. ",bd1.toPlainString());
12 bd1 = bd1.negate();
13 System.out.printf("bd1 = %s after negate. ",bd1.toPlainString());
14 System.out.println("The power of db2(123) is " + bd2.pow(2)。toPlainString());
15 }
16 /* 输出结果如下:
17 bd1 = 123456912.0123456890 after add.
18 bd1 = 15185200177.5185197470 after multiply.
19 bd1 = 15185200054.5185197470 after subtract.
20 bd1 = 123456911.0123456890 after divide.
21 bd1 = -123456911.0123456890 after negate.
22 The power of db2(123) is 15129
23 */
从结果中可以看出没有丢失精度。
③ 基于刻度的进位:
1 public static void main(String args[]) { 2 int decimalPlaces = 2; 3 BigDecimal bd = new BigDecimal("123456789.0123456890"); 4 //始终向下舍位 5 BigDecimal bd1 = bd.setScale(decimalPlaces, BigDecimal.ROUND_DOWN); 6 System.out.println(bd1.toString()); 7 //始终向上进位 8 BigDecimal bd2 = bd.setScale(decimalPlaces, BigDecimal.ROUND_UP); 9 System.out.println(bd2.toString());10 BigDecimal bd3 = new BigDecimal(3.14159);11 //四舍五入12 bd3 = bd3.setScale(3, BigDecimal.ROUND_HALF_UP);13 System.out.println(bd3.toString());14 }15 /* 输出结果如下:16 123456789.0117 123456789.0218 3.14219 */
大整型对象(BigInteger)
BigInteger和BigDecimal相比,大部分的功能是相同的,主要的差异为BigInteger仅仅表示大整数的封装,而不能表示浮点数,与此同时,BigInteger还提供了大量的位操作运算,这个和C++中的BitSet非常类似。如果我们的在应用中只是需要大整数,那么应该首先该类,而不是BigDecimal,如果我们的应用逻辑中有多于64种状态(long表示64bits)的情况,可以考虑用BigInteger的位操作功能。
①基本的数学运算和数学函数应用:
1 public static void main(String args[]) { 2 BigInteger bi1 = new BigInteger("1234567890123456890"); 3 BigInteger bi2 = BigInteger.valueOf(123L); 4 System.out.printf("bi1 = %s after added ",bi1.add(bi2)); 5 System.out.printf("bi1 = %s after multiply ",bi1.multiply(bi2)); 6 System.out.printf("bi1 = %s after subtract ",bi1.subtract(bi2)); 7 System.out.printf("bi1 = %s after divide ",bi1.divide(bi2)); 8 System.out.printf("bi1 = %s after negate ",bi1.negate()); 9 int exponent = 2;10 System.out.printf("bi1 = %s after pow ",bi1.pow(exponent));11 }12 /* 输出结果如下:13 bi1 = 1234567890123457013 after added14 bi1 = 151851850485185197470 after multiply15 bi1 = 1234567890123456767 after subtract16 bi1 = 10037137318076885 after divide17 bi1 = -1234567890123456890 after negate18 bi1 = 1524157875323883924401765803688472100 after pow19 */
②将BigInteger的值转换为各种进制的字符串表示:
1 public static void main(String args[]) { 2 BigInteger number = new BigInteger("2008"); 3 System.out.println("Number = " + number); 4 System.out.println("Binary = " + number.toString(2)); 5 System.out.println("Octal = " + number.toString(8)); 6 System.out.println("Hexadecimal = " + number.toString(16)); 7 number = new BigInteger("FF", 16); 8 System.out.println("Number = " + number); 9 System.out.println("Number = " + number.toString(16));10 }11 /* 输出结果如下:12 Number = 200813 Binary = 1111101100014 Octal = 373015 Hexadecimal = 7d816 Number = 25517 Number = ff18 */