1 //开平方
2 public static BigDecimal sqrt(BigDecimal number, int scale, int roundingMode) {
3 if (number.compareTo(BigDecimal.ZERO) < 0)
4 throw new ArithmeticException("sqrt with negative");
5 BigInteger integer = number.toBigInteger();
6 StringBuffer sb = new StringBuffer();
7 String strInt = integer.toString();
8 int lenInt = strInt.length();
9 if (lenInt % 2 != 0) {
10 strInt = '0' + strInt;
11 lenInt++;
12 }
13 BigInteger res = BigInteger.ZERO;
14 BigInteger rem = BigInteger.ZERO;
15 for (int i = 0; i < lenInt / 2; i++) {
16 res = res.multiply(BigInteger.TEN);
17 rem = rem.multiply(HUNDRED);
18
19 BigInteger temp = new BigInteger(strInt.substring(i * 2, i * 2 + 2));
20 rem = rem.add(temp);
21
22 BigInteger j = BigInteger.TEN;
23 while (j.compareTo(BigInteger.ZERO) > 0) {
24 j = j.subtract(BigInteger.ONE);
25 if (((res.add(j)).multiply(j)).compareTo(rem) <= 0) {
26 break;
27 }
28 }
29
30 res = res.add(j);
31 rem = rem.subtract(res.multiply(j));
32 res = res.add(j);
33 sb.append(j);
34 }
35 sb.append('.');
36 BigDecimal fraction = number.subtract(number.setScale(0, BigDecimal.ROUND_DOWN));
37 int fracLen = (fraction.scale() + 1) / 2;
38 fraction = fraction.movePointRight(fracLen * 2);
39 String strFrac = fraction.toPlainString();
40 for (int i = 0; i <= scale; i++) {
41 res = res.multiply(BigInteger.TEN);
42 rem = rem.multiply(HUNDRED);
43
44 if (i < fracLen) {
45 BigInteger temp = new BigInteger(strFrac.substring(i * 2, i * 2 + 2));
46 rem = rem.add(temp);
47 }
48
49 BigInteger j = BigInteger.TEN;
50 while (j.compareTo(BigInteger.ZERO) > 0) {
51 j = j.subtract(BigInteger.ONE);
52 if (((res.add(j)).multiply(j)).compareTo(rem) <= 0) {
53 break;
54 }
55 }
56 res = res.add(j);
57 rem = rem.subtract(res.multiply(j));
58 res = res.add(j);
59 sb.append(j);
60 }
61 return new BigDecimal(sb.toString()).setScale(scale, roundingMode);
62 }
63
64 public static BigDecimal sqrt(BigDecimal number, int scale) {
65 return sqrt(number, scale, BigDecimal.ROUND_HALF_UP);
66 }
67
68 public static BigDecimal sqrt(BigDecimal number) {
69 int scale = number.scale() * 2;
70 if (scale < 50)
71 scale = 50;
72 return sqrt(number, scale, BigDecimal.ROUND_HALF_UP);
73 }
74