计算一个尽可能大的素数
在有限的時間內,計算出一個盡可能大的素數
一.問題點
- 有限時間:在一個可接受的時間范圍內,并非依靠暴力求解
- 盡可能大:可計算素數的上限
- 素數:因數只有1和它本身的自然數
二.素數的生成
n 位的十進制位的大素數生成步驟如下:
三.Miller-Rabin 算法
Miller-Rabin 算法是一種基于概率的素性測試算法,因此該算法與一般的基于事實的真素性測試方法的區別是:存在一定的誤判率。但是在對于某個較大的待測數字進行多次測試的情況下,誤判率可以控制在可忽略范圍內。Miller-Rabin算法基于 Fermat 算法,屬于后者的變形、改進。
首先引入 Fermat定理:n是一個奇素數,a是任何整數(1 ≤ a ≤ n-1) ,則a^(n-1)≡1(mod n)根據此定理可以知道,對于給定的待測數字 n,可以通過設定素性測試算法,計算 w = a^(n-1)%n的結果來判定。
-
W!=1,n一定不是素數;
-
W==1,n可能是素數;
再引入二次探測定理,如果 n 是一個整數,且 0<x<n,則:x2%p=1 有: x= 1 / x = p-1。若n是素數,則( n-1 )一定是偶數,因此可令(n-1)=m*(2^q),其中m是正奇數( 若n是偶數,則上面的m*(2^q)一定可以分解成一個正奇數乘以2的k次方的形式 ),q是非負整數。
借助 Fermat 定理,進行如下測試:a^(m)%n、a^(2m)%n、a^(4m)%n、a^(m*(2^q))%n。進行這些測試的過程為:Miller-Rabin 測試。
誤判率:若 n 是素數,a 是小于 n 的正整數,則 n 對以 a 為基的Miller 測試,結果為真。Miller 測試進行 k次,將合數當成素數處理的錯誤概率最多不會超過 4^(-k)。
四.Java程序實現
/*** 題目8:計算一個盡可能大的素數* 題目描述:在有限的時間內,計算出一個盡可能大的素數。*/ package edu.sust;import java.util.Random; import java.util.Scanner;public class PrimeNumber {public static void main(String[] args) {long startTime = System.currentTimeMillis(); //開始時間Scanner scanner = new Scanner(System.in);long executeTime;//程序執行時間System.out.println("請輸入程序運行的時間(毫秒為單位):");executeTime = scanner.nextLong();long endTime = System.currentTimeMillis(); //結束時間int maxPrime = 2; //最大素數while (endTime - startTime < executeTime) {int num = getRandom();if (num > maxPrime) {if (MillerRabin(num, 3))maxPrime = num;}endTime = System.currentTimeMillis();}System.out.println(maxPrime);scanner.close();}public static int getRandom() {Random random = new Random();int num = random.nextInt(Integer.MAX_VALUE);if ((num & 1) != 1) {num++;//若最低位為偶數, 則將它加1, 以確保該素數為奇數}//檢查以確保 p 不能被任何小素數整除int[] primes = {3, 5, 7, 11, 13, 17, 19};for (int i = 0; i < primes.length; i++) {if (num % primes[i] == 0)return -1;}return num;}/*** 利用費馬小定理求大數冪取模** @param a 底數* @param b 指數* @param n 模數* @return 返回(a ^ b) mod n的值*/public static int FermatPower(int a, int b, int n) {int result = 1;while (b > 0) {if ((b & 1) == 1)result = (result * a) % n;if ((a * a) % n == 1 && a != 1 && a != n - 1)return -1;// 二次探測b >>= 1;a = (a * a) % n;}return result;}/*** Miller-Rabin素性測試** @param n 待測隨機數* @param time 檢測次數* @return 若通過測試,返回true,否則返回false*/public static boolean MillerRabin(int n, int time) {Random random = new Random();for (int i = 0; i < time; i++) {if (FermatPower(random.nextInt(n - 1) + 2, n - 1, n) != 1)return false;}return true;} }參考文獻
總結
以上是生活随笔為你收集整理的计算一个尽可能大的素数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot从入门到实战只需一篇
- 下一篇: 2020新年发红包Java实现