Calcule un número primo lo más grande posible

En un tiempo limitado, calcule un número primo lo más grande posible

1. problema

  • Tiempo limitado: dentro de un rango de tiempo aceptable, no confíe en la solución de fuerza bruta
  • Lo más grande posible: se puede calcular el límite superior de la prima
  • Número primo: el factor es solo 1 y su propio número natural

2. Generación de números primos.

Los pasos para generar un número primo grande con n dígitos decimales son los siguientes:

  1. Generar un número aleatorio de n bits p
  2. Si el bit más bajo es un número par, agregue 1 para asegurarse de que el número primo sea un número impar, lo que garantiza un ahorro promedio de la mitad del tiempo de cálculo
  3. Asegúrese de que p no es divisible por ningún factor pequeños, tales como 3, 5, 7, 11y similares, el propósito es excluir la posibilidad de que la mayor parte del número p se lamina, se probaron los pasos para reducir el número total de números primos p, lo que ahorra tiempo de cálculo. Utilicé todos los números primos menores que 20 excepto 2 (porque he verificado la paridad de p) para probar p para su divisibilidad
  4. Generar un número aleatorio, para llevar a cabo una Rabin- Millerprueba, para pasar la prueba si p es un ulterior genera un número aleatorio, y probar de nuevo seleccionar un valor menor, con el fin de garantizar una velocidad de funcionamiento más rápido, por tres Rabin-Millerpruebas (1 Parece ser suficiente, pero para garantizar una mayor precisión, puede hacerlo varias veces)
  5. Si p pasa la prueba, entonces p es un número primo; de lo contrario, agregue 2 al número probado original para obtener un nuevo número y luego pruebe el nuevo número hasta encontrar un número primo

3. Algoritmo de Miller-Rabin

Miller-RabinEl algoritmo es un algoritmo de prueba de primalidad probabilística, por lo tanto, la diferencia entre este algoritmo y el método de prueba de primalidad basado en hechos generales es que existe una cierta tasa de falsos positivos. Sin embargo, en el caso de múltiples pruebas para un gran número de pruebas, la tasa de falsos positivos se puede controlar dentro de un rango insignificante. Miller-RabinAlgoritmo basado en Fermatel algoritmo, esta última modificación, mejora.

Primero introdujo FermatTeorema: n es un primo impar, a es cualquier número entero (1 ≤ a ≤ n-1), a continuación, a^(n-1)≡1(mod n)de acuerdo con el teorema puede saber, por un número de prueba dado n, mediante el establecimiento de cálculo algoritmo de prueba de primalidad w = a^(n-1)%npara determinar los resultados.

  • W!=1, N no debe ser un número primo;

  • W==1, N puede ser un número primo;

Segundo detección reintroducción teorema, si n es un entero, y 0<x<n, a continuación: x2%p=1son: x= 1 / x = p-1. Si n es un número primo, ( n-1 )debe ser un número par, por lo que se puede hacer (n-1)=m*(2^q)que m sea un número impar positivo (si n es un número par, entonces lo anterior m*(2^q)debe descomponerse en un número impar positivo multiplicado por 2 a la potencia de k), y q es un número entero no negativo.

Con Fermatteorema, las siguientes a^(m)%n、a^(2m)%n、a^(4m)%n、a^(m*(2^q))%npruebas: . El proceso para realizar estas pruebas es: Miller-Rabinpruebas.

Tasa de error de juicio: si n es un número primo y a es un número entero positivo menor que n, entonces n es una prueba de Miller basada en ay el resultado es verdadero. La prueba de Miller se realiza k veces, y la probabilidad de error de tratar los números compuestos como números primos no excederá de 4 ^ (-k).

4. Implementación del programa 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;
    }
}

Referencias

  1. Liu Shaotao, Ling Jie. Algoritmo de encriptación de datos y generación y operación de grandes números primos [J]. Revista de la Universidad Tecnológica de Guangdong, 2001 (04): 27-31.
  2. Zhang Hong, Liu Xiaoxia, Zhang Ruoyan. Generación de grandes números primos seguros en el criptosistema de clave pública RSA [J]. Tecnología y desarrollo informáticos, 2008 (09): 137-139 + 143.
  3. Han Lie, Fu Xinghua, Liu Xinhua, et al. Un método para generar grandes números primos basados ​​en el criptosistema de clave pública RSA [J]. Journal of Guizhou University (Natural Science), 2005 (04): 101-104.
Publicado 395 artículos originales · ganó 130 · 200,000 vistas +

Supongo que te gusta

Origin blog.csdn.net/qq_40507857/article/details/103778071
Recomendado
Clasificación