java生成大素数_用BigInteger实现大素数生成算法
一.通過素?cái)?shù)的基本性質(zhì)
根據(jù)素?cái)?shù)的性質(zhì)(除了1和此整數(shù)(n)自身外,無法被其他自然數(shù)整除的數(shù)):即從2到n/2的數(shù)都不能整除n。
1 public static booleanisPrime(BigInteger num)2 {3 BigInteger two = BigInteger.valueOf(2);4 for(BigInteger i = two; !(i.compareTo(num.divide(two)) == 1); i =i.add(BigInteger.ONE))5 {6 if(num.remainder(i) == BigInteger.ZERO)7 {8 return false;9 }10 }11
12 return true;13 }
用大于2^63的數(shù)去測試,結(jié)果因?yàn)檫\(yùn)算量太大,運(yùn)行半個(gè)來小時(shí)也沒有結(jié)果出現(xiàn)。
二.通過素?cái)?shù)表
要提高速度就要減少進(jìn)入判斷方法中的循環(huán):
1.偶數(shù)可以排除
2.大的合數(shù)(即素?cái)?shù)的積)可以排除
排除偶數(shù)直接增加一個(gè)判斷即可實(shí)現(xiàn),而排除大的合數(shù)也通過產(chǎn)生一個(gè)素?cái)?shù)表實(shí)現(xiàn)。
這里引援51CTO網(wǎng)友 夢朝思夕的BOLG,即“一般來說整除100以內(nèi)的所有素?cái)?shù)可排除76%不是素?cái)?shù)的可能性整除256以內(nèi)的所有素?cái)?shù)可排除80%不是素?cái)?shù)的可能性。” 而我同樣地建大小為2000的表,private?static BigInteger[] primeList = new BigInteger[2000]
primeList[1999] = 17389
for(int i = 0, j = 2; i < 2000; j++)
{if(isPrime(j))
{
primeList[i]=BigInteger.valueOf(j);
i++;
}
}
再來一個(gè)方法判斷新生成的大數(shù)判斷是否為幾個(gè)素?cái)?shù)的積
public static booleanisNotPrimeProduct(BigInteger num)
{for(int i=0;i< 2000; i++)
{if(num.remainder(primeList[i]) ==BigInteger.ZERO)
{return false;
}
}return true;
}
素?cái)?shù)表太大也減慢速度,而且數(shù)值越大,素?cái)?shù)表判別的確定性就越小。要知道,我們要的是2^63。
三.通過費(fèi)馬(Fermat)素?cái)?shù)檢驗(yàn)
在網(wǎng)上查閱資料,知道可以運(yùn)用費(fèi)馬小定理檢驗(yàn)一個(gè)數(shù)是否不是合數(shù)。
費(fèi)馬小定理是數(shù)論中的一個(gè)定理:假如a是一個(gè)整數(shù),p是一個(gè)質(zhì)數(shù),那么
如果a不是p的倍數(shù),這個(gè)定理也可以寫成
根據(jù)費(fèi)馬小定理:如果p是素?cái)?shù),
,那么
如果我們想知道n是否是素?cái)?shù),我們在中間選取a,看看上面等式是否成立。如果對于數(shù)值a等式不成立,那么n是合數(shù)。如果有很多的a能夠使等式成立,那么我們可以說n?可能是素?cái)?shù),或者偽素?cái)?shù)。
在我們檢驗(yàn)過程中,有可能我們選取的a都能讓等式成立,然而n卻是合數(shù)。這時(shí)等式
被稱為Fermat liar。如果我們選取滿足下面等式的a
那么a也就是對于n的合數(shù)判定的Fermat witness。
而在這里我從cnblogs的Knuth_檔案學(xué)到了大量理論知識(shí)和算法的實(shí)現(xiàn)。(特別是蒙哥馬利快速積模算法:計(jì)算大數(shù)(x^y)%z)
用java實(shí)現(xiàn)如下
public staticBigInteger Montgomery(BigInteger n, BigInteger p, BigInteger m)
{
n=n.remainder(m) ;
BigInteger k=BigInteger.ONE;while(p.compareTo(BigInteger.ONE) == 0)
{if(!(p.remainder(BigInteger.ONE) ==BigInteger.ZERO))
{
k=(k.multiply(n)).remainder(m);
}
n=(n.multiply(n)).remainder(m);
p= p.divide(BigInteger.valueOf(2));
}return(n.multiply(k)).remainder(m);
}
接下來,我們就可以對一個(gè)大數(shù)使用費(fèi)馬素?cái)?shù)檢驗(yàn)可以判定這個(gè)大數(shù)是偽素?cái)?shù)。
從前2000素?cái)?shù)一一檢驗(yàn),而費(fèi)馬素?cái)?shù)檢驗(yàn)只是隨機(jī)化了。
public static booleanfermatPrimalityTest(BigInteger num)
{for(int i = 0; i < 2000; i++)
{if(!(Montgomery(primeList[i], num.subtract(BigInteger.ONE), num).compareTo(BigInteger.ONE) == 1)) //(x^y)%z
{return false;
}
}return true;
}
使用素?cái)?shù)表的前十個(gè)結(jié)果:
9223372036854775809
9223372036854775811
9223372036854775813
9223372036854775815
9223372036854775817
9223372036854775819
9223372036854775821
9223372036854775823
9223372036854775825
9223372036854775827
使用費(fèi)馬素?cái)?shù)檢驗(yàn)過的前十個(gè)結(jié)果:
9223372036854775817
9223372036854775837
9223372036854775889
9223372036854775903
9223372036854775907
9223372036854775931
9223372036854775937
9223372036854775939
9223372036854775949
9223372036854775963
四.總結(jié)
現(xiàn)在我們可以通過結(jié)果簡單的分析出出只是使用素?cái)?shù)表的結(jié)果有很多都通不過費(fèi)馬素?cái)?shù)檢驗(yàn),因?yàn)樗財(cái)?shù)表總有上界。最后可以通過Knuth所說的?拉賓米勒測試排除掉那些卡爾麥克(Carmichael)數(shù)。
最后再次感謝?夢朝思夕和 Knuth?兩位技術(shù)前輩,可以說我在這里只是把他們的心得進(jìn)一步總結(jié)。權(quán)當(dāng)筆記。
總結(jié)
以上是生活随笔為你收集整理的java生成大素数_用BigInteger实现大素数生成算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql --max_allowed_
- 下一篇: pve安装黑群晖直通硬盘_PVE+led