Генерация большого простого числа с указанными последними цифрами - PullRequest
11 голосов
/ 04 декабря 2010

Интересно, как можно сгенерировать 512-битное (155 десятичных цифр) простое число, последние пять десятичных цифр которого определены / фиксированы (например, *** 28071) ??

Принципы генерации простых простых чисел без каких-либо спецификаций вполне понятны, но мой случай идет дальше.

Любые подсказки, по крайней мере, с чего мне начать?

Java или C # предпочтительнее.

Спасибо!

Ответы [ 8 ]

7 голосов
/ 04 декабря 2010

Вы пробовали просто генерировать такие числа и проверять их? Я ожидаю, что это будет приемлемо быстро. Простая плотность уменьшается только как логарифм числа, поэтому я ожидаю, что вы попробуете несколько сотен чисел, пока не достигнете простого. ln(2^512) = 354 так что одно число из 350 будет простым.

Грубо говоря, теорема о простых числах гласит, что если выбрано случайное число около некоторого большого числа N, вероятность его простоты составляет около 1 / ln (N), где ln (N) обозначает натуральный логарифм N Например, около N = 10000, одно из девяти чисел является простым, тогда как около N = 1 000 000 000 только одно из каждых 21 чисел является простым. Другими словами, средний разрыв между простыми числами около N примерно равен ln (N)

(от http://en.wikipedia.org/wiki/Prime_number_theorem)

Вам просто нужно позаботиться о том, чтобы для ваших последних цифр существовал номер. Но я думаю, что это так же просто, как проверить, что последняя цифра не делится на 2 или 5 (т.е. это 1, 3, 7 или 9).

В соответствии с этими данными производительности вы можете выполнить около 2000 операций ModPow с 512-битными данными в секунду, и, поскольку простой простой тест проверяет 2^(p-1) mod p=1, что является одной операцией ModPow, вы должны генерировать несколько простых чисел с вашими свойствами в секунду.

Чтобы вы могли сделать (псевдокод):

BigInteger FindPrimeCandidate(int lastDigits)
{
    BigInteger i=Random512BitInt;
    int remainder = i % 100000;
    int increment = lastDigits-remainder;
    i += increment;
    BigInteger test = BigInteger.ModPow(2, i - 1, i);
    if(test == 1)
      return i;
    else
      return null;
}

И проведите более обширные первичные проверки результата этой функции.

7 голосов
/ 04 декабря 2010

Полагаю, единственный способ - это сначала сгенерировать случайное число из 150 десятичных цифр, затем добавить 28071 за ним, выполнив number = randomnumber * 100000 + 28071, а затем просто перебрать его с помощью чего-то вроде

while (!IsPrime(number))
    number += 100000;

Конечно, это может занять некоторое время для вычисления; -)

3 голосов
/ 04 декабря 2010

Как сказал @Doggot, но начинайте с минимально возможного 150-значного числа, которое заканчивается 28071, означает 100000 .... 0028071, теперь добавляйте его каждый раз с 100000 и для тестирования в основном используйте miller rabin, как и код, который я предоставил здесь , требуется некоторая настройка.Если возвращаемое значение истинно, в первую очередь проверьте его.

2 голосов
/ 05 декабря 2010

Пусть ABCDE будет пятизначным числом в базовой десятке, которое вы рассматриваете.Основываясь на теореме Дирихле об арифметических прогрессиях , если ABCDE и 100000 взаимно просты, то существует бесконечно много простых чисел вида 100000 * k + ABCDE.Поскольку вы ищете простые числа, ни 2, ни 5 в любом случае не разделят ABCDE, поэтому ABCDE и 100000 взаимно просты.Таким образом, существует бесконечно много простых чисел формы, которую вы рассматриваете.

2 голосов
/ 04 декабря 2010

Вы можете использовать сито, которое содержит только числа, удовлетворяющие вашему специальному условию, чтобы отфильтровать числа, кратные маленьким простым числам.

Для каждого маленького простого числа p вам нужно найти правильную начальную точку и шаг, выполнивучтите, что в сите присутствует только каждое 100-тысячное число.

Для чисел, которые выживают в сите, вы можете использовать BigInteger.isProbablePrime(), чтобы проверить, является ли оно простым с достаточной вероятностью.

1 голос
/ 04 декабря 2010

Я переписал алгоритм перебора из мира int в мир BigDecimal с помощью класса BigSquareRoot из http://www.merriampark.com/bigsqrt.htm. (обратите внимание, что от 1 до 1000, как говорят, ровно 168 простых чисел.)

Извините, но если вы поставите туда свой диапазон, т.е. <10 <sup>154 ; 10 155 -1>, вы можете позволить своему компьютеру работать, и когда вы выйдете на пенсию, у вас может быть результат ... это чертовски медленно!

Однако вы можете как-то найти хотя бы часть этого полезного в сочетании с другими ответами в этой теме.


package edu.eli.test.primes;

import java.math.BigDecimal;

public class PrimeNumbersGenerator {

  public static void main(String[] args) {
//    BigDecimal lowerLimit = BigDecimal.valueOf(10).pow(154); /* 155 digits */
//    BigDecimal upperLimit = BigDecimal.valueOf(10).pow(155).subtract(BigDecimal.ONE);

    BigDecimal lowerLimit = BigDecimal.ONE;
    BigDecimal upperLimit = new BigDecimal("1000");

    BigDecimal prime = lowerLimit;
    int i = 1;

    /* http://www.merriampark.com/bigsqrt.htm */
    BigSquareRoot bsr = new BigSquareRoot();
    upperLimit = upperLimit.add(BigDecimal.ONE);
    while (prime.compareTo(upperLimit) == -1) {

      bsr.setScale(0);
      BigDecimal roundedSqrt = bsr.get(prime);

      boolean isPrimeNumber = false;
      BigDecimal upper = roundedSqrt;
      while (upper.compareTo(BigDecimal.ONE) == 1) {

        BigDecimal div = prime.remainder(upper);
        if ((prime.compareTo(upper) != 0) && (div.compareTo(BigDecimal.ZERO) == 0)) {
          isPrimeNumber = false;
          break;
        } else if (!isPrimeNumber) {
          isPrimeNumber = true;
        }

        upper = upper.subtract(BigDecimal.ONE);
      }

      if (isPrimeNumber) {
        System.out.println("\n" + i + " -> " + prime + " is a prime!");
        i++;
      } else {
        System.out.print(".");
      }
      prime = prime.add(BigDecimal.ONE);
    }
  }

}

1 голос
/ 04 декабря 2010

Давайте рассмотрим перебор. Взгляните на этот очень интересный текст под названием «Лотерея простых чисел»:

Учитывая последнюю запись в последней таблице, ~ 2,79 * 10 ^ 14 простых чисел меньше, чем 10 ^ 16. Таким образом, примерно каждое 35-е число является простым в этом диапазоне.

РЕДАКТИРОВАТЬ: см. Комментарий CodeInChaos - если вы просто пройдете несколько тысяч 512-битных чисел с фиксированными последними 5 цифрами, вы быстро найдете одно.

1 голос
/ 04 декабря 2010

Вы можете расширить один из стандартных методов генерации больших простых чисел , добавив дополнительное ограничение, т. Е. Последние 5 десятичных цифр должны быть правильными. Наивно, вы можете просто добавить это как дополнительный тест, но это увеличит время на поиск подходящего простого числа на 10 ^ 5.

Не так наивно: сгенерируйте случайное 512-битное число, затем установите достаточное количество младших битов, чтобы десятичное представление заканчивалось требуемой последовательностью. Затем продолжите обычные тесты на простоту.

...