1だけならぶ素数

このワークシートはMath by Codeの一部です。
<レプ・ユニット素数ってなんだっけ?>
レプ・ユニット数は、反復する1、つまり、repeatedUnitsの略した言い方。
レプ・ユニット素数はどのくらいあるでしょう。
111=999/9=(1000-1)/9=(10^3-1)/9と表せるように、
一般に(10^n-1)/9で111...1のように1だけが並ぶ整数が作れます。
nが9973以下では、n=2,19,23,317,1031の5個だけだといわれています。
実験してみましょう。
juliaで素数判定関数をまた使います。次に、juliaでn=9999までの整数に対して
レプ・ユニット数(10^n-1)/9に素数filterをかけよう。
[IN]julia
#======================
N=[x for x in 2:30]
Rp=map(n->(n,((10^n-1)÷9)),N)
println(N)
println(Rp)
#======================
[OUT]
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
[(2, 11), (3, 111), (4, 1111), (5, 11111), (6, 111111), (7, 1111111), (8, 11111111), (9, 111111111), (10, 1111111111), (11, 11111111111), (12, 111111111111), (13, 1111111111111), (14, 11111111111111), (15, 111111111111111), (16, 1111111111111111), (17, 11111111111111111), (18, 111111111111111111), (19, -938527119301061290), (20, 862919959050249102), (21, 430646668853801415), (22, 207190227713669347), (23, 22264046724521073), (24, 222640467245210737), (25, 176766442039934975), (26, -281973810012822641), (27, -770099869716054016), (28, 497554224488149447), (29, 876265784057149667), (30, 564104918922807068)]
<参考>
(・素数リストの作り方、素数判定についてはこちら、
・リストにfilterをかける方法についてはこちら)
残念なら桁溢れが19けたで起きている。
juliaの整数intは19ケタが限界なので、
BigInt()を使って、ケタの限界をこえるように改造しよう。
1が3の倍数個あると3の倍数になるからとばそう。
1が2より大きい偶数個(2n)あると、左右にわけた1がn個ならんだ数の倍数になるからとばそう。
いやいや、
それだけではない。
また、m,nに対するレプ・ユユニット数Rm,Rnがあるとき、mがnの倍数ならば、RmはRnの倍数になる。
すると、mが合成数ならば、Rmはmの因子nのRnを因数にもつから、合成数になる。
レプユニット素数Rpを探すには、pが素数であることは必要だが、十分でなない。
これって、メルセンヌ素数と同様に、mが素数であることは必要だが十分ではないときと同じだね。
質問:m,nに対するレプ・ユユニット数Rm,Rnがあるとき、mがnの倍数ならば、RmはRnの倍数になる。これはどうやって証明しますか。
レプユニット素数の候補数をならべよう。
Pythonの場合はJuliaより無名関数やmap,filterでリストを作ると、記述が長めになる。
だから、約数個数を求める関数divCountを作って、1行に詰め込みすぎないようにしよう。
2から100までの整数のリストMで、dicCountが2個になる整数Pが素数のリストとなる。
素数個の1を並べることで、レプ・ユニット素数の候補ができる。
#[IN]Python
#=================================
M=list(range(2,100))
divCount=lambda n:len(list(filter(lambda m:n % m==0, list(range(1,n+1)))))
P=[x for x in M if divCount(x)==2]
Rp=list(map(lambda n:(n,((10**n-1)//9)),P))
print(P)
print(Rp)
#==================================
Juliaでは、divcountを関数にしなくても、filterの中の無名関数で簡単にかける。
#[IN]Julia
#=================================
P=filter(n->length(filter( m -> n % m==0,1:n))==2, 2:100)
#べき乗のBigInt()は底につける。
Rp=map(n->(n,(BigInt(10)^n-1)÷BigInt(9)), P)
println(P)
println(Rp)
#=================================
[OUT]
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
[(2, 11),
(3, 111),
(5, 11111),
(7, 1111111),
(11, 11111111111),
(13, 1111111111111),
(17, 11111111111111111),
(19, 1111111111111111111),
(23, 11111111111111111111111),
(29, 11111111111111111111111111111),
(31, 1111111111111111111111111111111),
(37, 1111111111111111111111111111111111111),
(41, 11111111111111111111111111111111111111111),
(43, 1111111111111111111111111111111111111111111),
(47, 11111111111111111111111111111111111111111111111),
(53, 11111111111111111111111111111111111111111111111111111),
(59, 11111111111111111111111111111111111111111111111111111111111),
(61, 1111111111111111111111111111111111111111111111111111111111111),
(67, 1111111111111111111111111111111111111111111111111111111111111111111),
(71, 11111111111111111111111111111111111111111111111111111111111111111111111),
(73, 1111111111111111111111111111111111111111111111111111111111111111111111111),
(79, 1111111111111111111111111111111111111111111111111111111111111111111111111111111),
(83, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111),
(89, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111),
(97, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111)]
100以下のレプ・ユニット素数の候補が即座に表示できた。
juliaのいいところは,mapやfilterのリストへの操作が簡潔にかけるところだ。
デメリットはPythonのように、何もしなくても多桁(多倍長整数)対応になるわけではなく、
BigIntでくるむ必要があるため、可読性が落ちることだね。
2007年までに9個しか見つかっていないらしい。
pythonで検証してみる。
2,19の2個だけで数分かかる。
次は23の1個だけでもかなり時間がかかる。
317を見つけるには何かしら手段をさらに工夫が必要となりそうだ。
[IN]Python
#===========================================================
def isPrime(n):
lim = int(round(n**0.5))
for num in range(2,lim):
if n % num ==0:
return False
return True
M=list(range(2,20))
divCount=lambda n:len(list(filter(lambda m:n % m==0, list(range(1,n+1)))))
P=[x for x in M if divCount(x)==2]
R=list(map(lambda n:(n,((10**n-1)//9)),P))
Rp=list(filter(lambda n:isPrime((10**n-1)//9),P))
print(P)
print(R)
print(Rp)
#===========================================================
[2, 3, 5, 7, 11, 13, 17, 19]
[(2, 11), (3, 111), (5, 11111), (7, 1111111), (11, 11111111111), (13, 1111111111111), (17, 11111111111111111), (19, 1111111111111111111)]
[2, 19]
geogebraではn=19けた以上は探さずに終了している。
n=19というので、juliaが19けたが桁溢れしたことを思い出すね。
juliaでも同様なコードをかいて実行しても、時短にはならなかった。残念。
質問:rustでn=317までのレプ・ユニット素数を検索するには、どうしましょう。
素数リスト、レピュニット数リスト、レピュニット素数リストの順に作るのは同じですが、
最後の素数判定でスピードアップの工夫をします。
rustが高速なのと、素数判定が高速なので、あっという間に結果がでます。
約数2個の整数、つまり、素数のリストをつくりましょう。
2からlast=330までの範囲を対象に
約数2個というフィルターをかけて集めます。
let prime: Vec = (2..=last)
.filter(|&n| (1..=n).filter(|&m| n % m == 0).count() == 2)
.collect();
println!("素数リスト: {:?}", prime);
次に1が素数個ならんだレピュニット数のリストを作りましょう。
素数を対象に、10の素数乗ー1を9で割った商に変換して、集めます。
// Rn = (10^n - 1) / 9
let repunit: Vec = prime
.iter()
.map(|&x| (ten.pow(x as u32) - &one) / &nine)
.collect();
println!("レピュニット数リスト(Rn): {:?}", repunit);
最後に、レピュニット数Rnが素数かどうかを判定しますが。
1が330個ならんだ数が素数かどうかまで調べる計算は、
通常の素数判定(約数2個とか、2から平方根までに約数が1個もないとか)では
時間が膨大になり、PCが永遠の眠りにつきます。
そこで、乱択法を使いましょう。
円の面積をモンテカルロ法で調べるように、乱数を使って近似的に調べます。
Miller-Rabin法です。
nが素数ならば、
n - 1を2で割り切れるまで何度も割りましょう。
その割り算回数をk、最後の奇数の商をqとすると、n-1 = 2^k * q です。
2 <= a < n-1 の範囲でランダムな整数 a を選択して、
a^q ≡ 1 (mod n) または、
a^[(2^(i-1))*q] ≡-1(mod n)となるiが1からkの中に1つある。
このことの対偶から、
ランダムな整数 aで、mod nで
a^q !≡ 1 (mod n) and 1からkのどのiでもa^[(2^(i-1))*q] ≡-1(mod n)
ならば、nが合成数。このときのaを合成数の証人といいます。
Miller-Rabin法では証人aが4分3の合成数以上確保できるので、10回連続失敗する可能性は100万分の1程度と少ない(しかし、ゼロではない。)
合成数の判定がでないと、相当の確率で素数と言える。しかし、素数でない可能性もの残る。
アルゴリズムとしては、≡1, ≡-1のすべての判定をすべて不合格なら
最後に合成数と言えるので、「たぶん素数か」の問いに対してfalseを返す。
反対に、≡1, ≡-1が言えた時点で次の試行に進みどれも合格したときにtrueにたどり着く。
[IN]rust in Cargo.toml
[dependencies]
rand = "0.8"
num-bigint = { version = "0.4", features = ["rand"] } # rand機能を有効にする
num-traits = "0.2"
num-iter = "0.1"
[IN]rust in main.rs
use num_bigint::{BigInt, RandBigInt, ToBigInt};
use num_traits::{One, Zero};
use rand::thread_rng; // rng ではなく thread_rng
fn main() {
let one: BigInt = One::one();
let ten: BigInt = 10.to_bigint().unwrap();
let nine: BigInt = 9.to_bigint().unwrap();
let last = 330; //n=330までやってみる。
let prime: Vec< i64 > = (2..=last)
.filter(|&n| (1..=n).filter(|&m| n % m == 0).count() == 2)
.collect();
println!("素数リスト: {:?}", prime);
// Rn = (10^n - 1) / 9
let repunit: Vec< BigInt > = prime
.iter()
.map(|&x| (ten.pow(x as u32) - &one) / &nine)
.collect();
println!("レピュニット数リスト(Rn): {:?}", repunit);
let repunit_prime: Vec< BigInt > = repunit
.into_iter()
.filter(|rn| is_prime_miller_rabin(rn, 10)) // 10回テスト
.collect();
println!("レピュニット素数: {:?}", repunit_prime);
}
fn is_prime_miller_rabin(n: &BigInt, repeat: usize) -> bool {
let zero = BigInt::zero();
let one = BigInt::one();
let two = 2.to_bigint().unwrap();
if n <= &one { return false; }
if n <= &3.to_bigint().unwrap() { return true; }
if n % &two == zero { return false; }
// n - 1 = 2^k * q を計算して、kとqを絞り出す。
let n_minus_one = n - &one;
let mut q = n_minus_one.clone();
let mut k = 0u32;
while &q % &two == zero {
q /= &two;
k += 1;
}
//乱択の準備
let mut rng = thread_rng();
//repeat回試行する。
'outer: for _ in 0..repeat {
// 2 <= a < n-1 の範囲でランダムな整数 a を選択
let a = rng.gen_bigint_range(&two, &n_minus_one);
// v = a^q mod n を求めてテストの準備
let mut v = a.modpow(&q, n);
// a^q ≡ 1 (mod n) なら次の試行へ
if v == one || v == n_minus_one {
continue 'outer;
}
// a^{ (2^i) * q } ≡ -1 (mod n) になる i があるかチェック
for _ in 0..k - 1 {
v = v.modpow(&two, n); // 順次 2乗していく
if v == n_minus_one {
continue 'outer;
}
}
// どの条件も満たさなければ、間違いなくnは合成数であり、aはその証人となる。
return false;
}
//たぶん素数
true
}
[OUT]cargo run --quiet
素数リスト: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317]
レピュニット数リスト(Rn): [11, 111, 11111, 1111111, 11111111111, 1111111111111, 11111111111111111, 1111111111111111111, 11111111111111111111111, 11111111111111111111111111111, 1111111111111111111111111111111, 1111111111111111111111111111111111111, 11111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111]
レピュニット素数: [11, 1111111111111111111, 11111111111111111111111, 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111]