teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

回答

2015/02/10 04:44

投稿

argius
argius

スコア9396

answer CHANGED
@@ -1,1 +1,69 @@
1
- `bigIntSqrt`で時間がかかっているのではないでしょうか。`bigIntSqrt`の実装を教えてください。
1
+ `bigIntSqrt`で時間がかかっているのではないでしょうか。`bigIntSqrt`の実装を教えてください。
2
+
3
+ ---
4
+
5
+ (回答)
6
+
7
+ `BigInteger`のインスタンスを取得する際に、`new BigInteger(String)`を使わずに`BigInteger.valueOf(long)`を使ったほうがパフォーマンスが良いです。また、何度も使う値は毎回`new`せずに、定数にしましょう。
8
+
9
+ それ以外にも、こんな感じでメソッドを作って置き換えると、コードの見通しが良くなります。
10
+
11
+ 計算結果があっているかどうかは確認できていません。
12
+
13
+ ```lang-java
14
+ // Java5以降
15
+
16
+ import static java.math.BigInteger.*; // ZERO, ONE
17
+ import java.math.BigInteger;
18
+ import java.util.Arrays;
19
+ import java.util.List;
20
+
21
+ public final class App {
22
+
23
+ static final BigInteger TWO = BigInteger.valueOf(2);
24
+ static final BigInteger THREE = BigInteger.valueOf(3);
25
+ static final BigInteger FIVE = BigInteger.valueOf(5);
26
+ static final BigInteger SEVEN = BigInteger.valueOf(7);
27
+ static List<BigInteger> smallPrimeNumbers = Arrays.asList(TWO, THREE, FIVE, SEVEN);
28
+
29
+ public static boolean isSosuuNum(BigInteger x) {
30
+ if (isNotDivisible(x, TWO) && isNotDivisible(x, THREE) && isNotDivisible(x, FIVE) && isNotDivisible(x, SEVEN)
31
+ && x.equals(ONE)) {
32
+ for (BigInteger bN = bigIntSqrt(x); bN.compareTo(ONE) > 0; bN = bN.subtract(ONE)) {
33
+ if (isDivisible(x, bN)) {
34
+ break;
35
+ }
36
+ else if (bN.equals(TWO)) {
37
+ return true;
38
+ }
39
+ }
40
+ }
41
+ else if (smallPrimeNumbers.contains(x)) {
42
+ return true;
43
+ }
44
+ return false;
45
+ }
46
+
47
+ private static BigInteger bigIntSqrt(BigInteger x) {
48
+ BigInteger div = ZERO.setBit(x.bitLength() / 2);
49
+ BigInteger div2 = div;
50
+ for (;;) {
51
+ BigInteger y = div.add(x.divide(div)).shiftRight(1);
52
+ if (y.equals(div) || y.equals(div2)) {
53
+ return y;
54
+ }
55
+ div2 = div;
56
+ div = y;
57
+ }
58
+ }
59
+
60
+ static boolean isDivisible(BigInteger a, BigInteger b) {
61
+ return a.mod(b).equals(ZERO);
62
+ }
63
+
64
+ static boolean isNotDivisible(BigInteger a, BigInteger b) {
65
+ return !a.mod(b).equals(ZERO);
66
+ }
67
+
68
+ }
69
+ ```