处理大数字BigInteger与BigDecimal
关键技术剖析:
BigInteger:支持任意精度的整数,可以精确地表示任意大小的整数值,同时在运算过程中不会丢失任何信息。
BigDecimal:可以精确地表示任意精度的小数,同时在运算过程中不会丢失任何信息。
源码:
1.import java.math.BigDecimal;
2.
3.import java.math.BigInteger;
4.
5.
6.
7.
8.
9.public class BigNumber {
10.
11.
12.
13.//默认除法运算精度,即保留小数点多少位
14.
15.private static final int DEFAULT_DIV_SCALE = 10;
16.
17.
18.
19.//这个类不能实例化
20.
21.private BigNumber() {
22.
23.}
24.
25.
26.
27.
28.
29.public static double add(double v1, double v2) {
30.
31.BigDecimal b1 = new BigDecimal(Double.toString(v1));
32.
33.BigDecimal b2 = new BigDecimal(Double.toString(v2));
34.
35.return (b1.add(b2)).doubleValue();
36.
37.}
38.
39.
40.
41.
42.
43.public static double sub(double v1, double v2) {
44.
45.BigDecimal b1 = new BigDecimal(Double.toString(v1));
46.
47.BigDecimal b2 = new BigDecimal(Double.toString(v2));
48.
49.return (b1.subtract(b2)).doubleValue();
50.
51.}
52.
53.
54.
55.
56.
57.public static double mul(double v1, double v2) {
58.
59.BigDecimal b1 = new BigDecimal(Double.toString(v1));
60.
61.BigDecimal b2 = new BigDecimal(Double.toString(v2));
62.
63.return (b1.multiply(b2)).doubleValue();
64.
65.}
66.
67.
68.
69.
70.
71.public static double div(double v1, double v2) {
72.
73.return div(v1, v2, DEFAULT_DIV_SCALE);
74.
75.}
76.
77.
78.
79.
80.
81.public static double div(double v1, double v2, int scale) {
82.
83.if (scale < 0) {
84.
85.System.err.println("除法精度必须大于0!");
86.
87.return 0;
88.
89.}
90.
91.BigDecimal b1 = new BigDecimal(Double.toString(v1));
92.
93.BigDecimal b2 = new BigDecimal(Double.toString(v2));
94.
95.return (b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP)).doubleValue();
96.
97.}
98.
99.
100.
101.
102.
103.public static BigInteger getFactorial(int n) {
104.
105.if (n < 0) {
106.
107.System.err.println("n必须大于等于0!");
108.
109.return new BigInteger("-1");
110.
111.} else if (n == 0) {
112.
113.return new BigInteger("0");
114.
115.}
116.
117.//将数组换成字符串后构造BigInteger
118.
119.BigInteger result = new BigInteger("1");
120.
121.for (; n > 0; n--) {
122.
123.//将数字n转换成字符串后,再构造一个BigInteger对象,与现有结果做乘法
124.
125.result = result.multiply(new BigInteger(new Integer(n).toString()));
126.
127.}
128.
129.return result;
130.
131.}
132.
133.
134.
135.public static void main(String[] args) {
136.
137.
138.
139.// 如果我们编译运行下面这个程序会看到什么?
140.
141.System.out.println(0.05 + 0.01);
142.
143.System.out.println(1.0 - 0.42);
144.
145.System.out.println(4.015 * 100);
146.
147.System.out.println(123.3 / 100);
148.
149.// 0.060000000000000005
150.
151.// 0.5800000000000001
152.
153.// 401.49999999999994
154.
155.// 1.2329999999999999
156.
157.
158.
159.//计算阶乘,可以将n设得更大
160.
161.int n = 30;
162.
163.System.out.println("计算n的阶乘" + n + "! = " + BigNumber.getFactorial(n));
164.
165.
166.
167.//用double构造BigDecimal
168.
169.BigDecimal bd1 = new BigDecimal(0.1);
170.
171.System.out.println("(bd1 = new BigDecimal(0.1)) = " + bd1.toString());
172.
173.//用String构造BigDecimal
174.
175.BigDecimal bd2 = new BigDecimal("0.1");
176.
177.System.out.println("(bd2 = new BigDecimal("0.1")) = "
178.
179.+ bd2.toString());
180.
181.
182.
183.BigDecimal bd3 = new BigDecimal("0.10");
184.
185.//equals方法比较两个BigDecimal对象是否相等,相等返回true,不等返回false
186.
187.System.out.println("bd2.equals(bd3) = " + bd2.equals(bd3));//false
188.
189.//compareTo方法比较两个BigDecimal对象的大小,相等返回0,小于返回-1,大于返回1。
190.
191.System.out.println("bd2.compareTo(bd3) = " + bd2.compareTo(bd3));//0
192.
193.
194.
195.//进行精确计算
196.
197.System.out.println("0.05 + 0.01 = " + BigNumber.add(0.05, 0.01));
198.
199.System.out.println("1.0 - 0.42 = " + BigNumber.add(1.0, 0.42));
200.
201.System.out.println("4.015 * 100 =" + BigNumber.add(4.015, 100));
202.
203.System.out.println("123.3 / 100 = " + BigNumber.add(123.3, 100));
204.
205.}
206.
207.}
运行结果:
0.060000000000000005
0.5800000000000001
401.49999999999994
1.2329999999999999
计算n的阶乘30! = 265252859812191058636308480000000
(bd1 = new BigDecimal(0.1)) = 0.1000000000000000055511151231257827021181583404541015625
(bd2 = new BigDecimal(“0.1”)) = 0.1
bd2.equals(bd3) = false
bd2.compareTo(bd3) = 0
0.05 + 0.01 = 0.06
1.0 - 0.42 = 1.42
4.015 * 100 =104.015
123.3 / 100 = 223.3
源码分析:
BigInteger与BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,由于创建对象会引起开销,因此它们不适合于大量的数学运算,应尽量使用long、float、double等基本类型做科学计算或者工程计算。设计BigInteger与BigDecimal的目的是用来精确地表示大整数和小数,常用于商业计算中。
BigDecimal够造方法的参数类型有4种,其中的两个用BigInteger构造,另一个是用double构造,还有一个使用String构造。应该避免使用double构造BigDecimal
,因为:有些数字用double根本无法精确表示,传给BigDecimal构造方法时就已经不精确了。比如,new BigDecimal(0.1)得到的值是0.1000000000000000055511151231257827021181583404541015625。
使用new BigDecimal("0.1")得到的值是0.1
。因此,如果需要精确计算,用String构造BigDecimal,避免用double构造,尽管它看起来更简单!
equals()方法认为0.1和0.1是相等的,返回true,而认为0.10和0.1是不等的,结果返回false。方法compareTo()则认为0.1与0.1相等,0.10与0.1也相等。
所以在从数值上比较两个BigDecimal值时,应该使用compareTo()而不是 equals()
。另外还有一些情形,任意精度的小数运算仍不能表示精确结果。例如,1除以9会产生无限循环的小数 .111111…。出于这个原因,
在进行除法运算时,BigDecimal可以让您显式地控制舍入
。
常用方法
1.valueOf(parament); 将参数转换为制定的类型
比如
1.int a=3;
2.BigInteger b=BigInteger.valueOf(a);
3.则b=3;
4.String s=”12345”;
5.BigInteger c=BigInteger.valueOf(s);
6.则c=12345;
2.add(); 大整数相加
BigInteger a=new BigInteger(“23”);
BigInteger b=new BigInteger(“34”);
a.add(b);
3.subtract(); 相减
4.multiply(); 相乘
5.divide(); 相除取整
6.remainder();取余
7.pow(); a.pow(b)=a^b
8.gcd(); 最大公约数
9.abs(); 绝对值
10.negate();取反数
11.mod(); a.mod(b)=a%b=a.remainder(b);
12.max(); min();
13.punlic int comareTo();
14.boolean equals(); 是否相等
BigInteger构造函数:
一般用到以下两种:
BigInteger(String val);
将指定字符串转换为十进制表示形式;
BigInteger(String val,int radix);
将指定基数的BigInteger的字符串表示形式转换为BigInteger
基本常量:
A=BigInteger.ONE 1
B=BigInteger.TEN 10
C=BigInteger.ZERO 0