実現したいこと
実装した3つの素数判定法の結果と計測時間をエクセルに出力したいです。フェルマーテスト、ミラーラビンテスト、aks判定法の3つを実際に実装しており、その判定結果と計測時間のプログラムも実装済みです。
理想としては、エクセルの1行目を左から、判定する数、フェルマー結果、フェルマー時間、ミラーラビンテスト結果...のようにしたいです。
発生している問題・分からないこと
現在はある一つの数について判定をするようになっていますが、そこは気にせずに教えていただきたいです。
該当のソースコード
Python
1#フェルマーテスト 2import math 3import random 4 5 6 7def is_prime(n): 8 if n == 1: 9 return False 10 if n == 2: 11 print("%d is prime." % n) 12 return True 13 14 passed_all = True 15 16 for i in range(20): # 20は試行回数 17 a = random.randint(2, n - 1) 18 19 if math.gcd(n, a) != 1: #互いに素ではないから合成数 20 continue 21 22 if pow(a, n - 1, n) != 1: 23 passed_all = False 24 #print("%d is not passed" % a) 25 return False 26 else: 27 #print("%d is passed" % a) 28 continue 29 30 if passed_all: 31 #print("%d is probably prime." % n) 32 return True 33 34 return True 35 36 37 38 39
Python
1#ミラーラビンテスト 2import random 3import math 4 5def MillerRabinTest(n): 6 if n == 1: 7 return False 8 9 if n == 2: 10 #print("%d is prime." % n) 11 return True 12 13 if n % 2 == 0: 14 #print("%d is not prime" % n) 15 return False 16 17 passed_all = True 18 19 s, d = CountSd(n) 20 21 for i in range(20): #試行回数 22 a = random.randint(2, n - 1) 23 24 if pow(a, d, n) == 1: 25 #print("%d is passed." % a) 26 continue 27 28 u = 0 29 30 while u < s: 31 if pow(a, d * (2 ** u), n) == n - 1: #-1=n-1 32 #print("%d is passed" % a) 33 break 34 u += 1 35 36 else: 37 passed_all = False 38 #print("%d is not passed" % a) 39 return False 40 41 if passed_all: 42 #print("%d is probably prime." % n) 43 return True 44 45 return True 46 47 48 49 50def CountSd(n): 51 if n % 2 == 0: 52 return False 53 if n % 2 == 1: 54 d = n - 1 55 s = 0 56 while d % 2 == 0: 57 d //= 2 58 s += 1 59 return s, d 60 61 62 63
Python
1#aks 2import math 3import numpy as np 4 5def is_prime1(n): 6 if n == 1: return False 7 8 # Step 1 9 if is_perfect_power(n): return False 10 11 # Step 2 12 r = enough_order_modulo(n) 13 14 # Step 3 15 for a in range(2, min(r+1, n)): 16 if n % a == 0: 17 return False 18 19 # Step 4 20 if n <= r: return True 21 22 # Step 5 23 for a in range(1, int(math.sqrt(tortient(r)) * math.log(n)) + 1): 24 if not is_congruent(a, n, r): 25 return False 26 27 # Step 6 28 return True 29 30# nが累乗数かどうかを判定 31def is_perfect_power(n): 32 size = int(math.log2(n) + 1) 33 for k in range(2, size): 34 pn = int(math.pow(n, 1 / k)) 35 if pn ** k == n or (pn+1) ** k == n: return True 36 return False 37 38# 十分大きな位数を持つ最小の数 39def enough_order_modulo(n): 40 a = int(math.log(n) ** 2) 41 for r in range(1, n): 42 order = 0 43 prod = 1 44 for e in range(1, r): 45 prod = prod * n % r 46 if prod == 1: 47 order = e 48 break 49 if order > a: 50 return r 51 return n 52 53# オイラーのトーシェント関数 54def tortient(r): 55 ps = primes(r) 56 res = r 57 for p in ps: 58 res = res * (p - 1) / p 59 return res 60 61# rの素因数のリスト 62def primes(r): 63 n = r 64 res = set() 65 for p in range(2, int(math.sqrt(r)) + 1): 66 while n % p == 0: 67 res.add(p) 68 n /= p 69 return res 70 71# (x + a)^n と x^n + a が mod x^r - 1, n で合同かどうかを判定 72def is_congruent(a, n, r): 73 p = PolynomialModulo() 74 ls1 = p.pow([a, 1], n, r) 75 76 i = n % r 77 ls2 = [0] * (i + 1) 78 ls2[0] = a % n 79 ls2[i] = 1 80 81 return ls1 == ls2 82 83class PolynomialModulo(object): 84 85 def pow(self, ls, n, r): 86 self.ls = ls 87 self.n = n 88 self.r = r 89 90 return self.__pow(self.n) 91 92 def __pow(self, m): 93 if m == 1: return self.ls 94 if m % 2 == 0: 95 pls = self.__pow(m // 2) 96 return self.__product(pls, pls) 97 else: 98 return self.__product(self.__pow(m - 1), self.__pow(1)) 99 100 def __product(self, ls1, ls2): 101 res = [0] * min(len(ls1) + len(ls2) - 1, self.r) 102 for i in range(len(ls1)): 103 for j in range(len(ls2)): 104 res[(i + j) % self.r] += ls1[i] * ls2[j] 105 l = len(res) 106 for k in reversed(range(l)): 107 res[k] %= self.n 108 if k == len(res) - 1 and res[k] == 0: res.pop(k) 109 return res 110 111 112 113
Python
1import fermat_test 2import MillerRabinTest 3import aks_prime_test 4import time 5 6 7start = time.perf_counter() 8print(fermat_test.is_prime(561)) 9end = time.perf_counter() 10print(end-start) 11#処理時間出力 12 13start = time.perf_counter() 14print(MillerRabinTest.MillerRabinTest(561)) 15end = time.perf_counter() 16print(end-start) 17#処理時間出力 18 19start = time.perf_counter() 20print(aks_prime_test.is_prime1(561)) 21end = time.perf_counter() 22print(end-start) 23#処理時間出力
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
データをエクセルに出力する方法を調べたが、データを配列にする必要があるとおもい、理解できず断念した。
補足
特になし