Как найти ближайшее простое число?

есть ли хороший алгоритм, чтобы найти ближайшее простое число к заданному real номер? Мне нужно искать только в пределах первых 100 простых чисел или около того.

в настоящее время у меня есть куча простых чисел, хранящихся в массиве, и я проверяю разницу по одному числу за раз (O(n)?).

13 ответов


вместо отсортированного списка простых чисел, учитывая относительно небольшой целевой диапазон, есть массив, индексированный всеми нечетными числами в диапазоне (вы знаете, что нет четных простых чисел, кроме частного случая 2) и содержащий ближайшее простое число. Поиск решения становится O (1) по времени.

Я думаю, что 100-й Прайм-это около 541. массив из 270 [малых] ints-это все, что нужно.

этот подход особенно актуален, учитывая относительно высокую плотность простых чисел (в частности относительно нечетных чисел), в диапазоне ниже 1000. (Как это влияет на размер двоичного дерева)


Если вам нужно только выполнить поиск в первых 100 простых числах или около того, просто создайте отсортированную таблицу этих простых чисел и выполните двоичный поиск. Это приведет вас либо к одному простому числу, либо к точке между двумя, и вы проверяете, какой из них ближе.

Edit: учитывая распределение простых чисел в этом диапазоне, вы, вероятно, могли бы ускорить (немного), используя интерполяционный поиск - вместо того, чтобы всегда начинать с середины таблицы, используйте линейную интерполяцию, чтобы угадать больше точная отправная точка. 100-е простое число должно быть где-то около 250 или около того (на предположение-я не проверял), поэтому, если (например) вы хотите, чтобы он был ближе к 50, вы бы начали около 1/5 пути в массив, а не на полпути. Вы можете в значительной степени рассматривать простые числа как начинающиеся с 1, поэтому просто разделите число, которое вы хотите, на наибольшее в вашем диапазоне, чтобы получить догадку в начальной точке.


ответы до сих пор довольно сложным, учитывая задачи. Первая сотня простых чисел!--3--> - все меньше 600. Я бы создал массив размером 600 и поместил в каждом значение ближайшего простого числа к этому числу. Затем, учитывая номер для тестирования, я бы округлил его вверх и вниз, используя floor и ceil функции для получения одного или двух ответов кандидата. Простое сравнение с расстояниями до этих чисел даст вам очень быстрый ответ.


самым простым подходом было бы сохранить простые числа в отсортированном списке и изменить алгоритм для выполнения двоичного поиска.

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


самый быстрый алгоритм? Создайте таблицу поиска с элементами p[100]=541 и верните результат для floor(x) со специальной логикой для x на [2,3]. Это будет O(1).


вы должны отсортировать свой номер в массиве, тогда вы можете использовать бинарный поиск. Этот алгоритм имеет производительность O(log n) в худшем случае.


public static boolean p(int n){

    for(int i=3;i*i<=n;i+=2) {
        if(n%i==0)
            return false;
    }
    return n%2==0? false: true; }

public static void main(String args[]){
    String n="0";
    int x = Integer.parseInt(n);
    int z=x;
    int a=0;
    int i=1;
    while(!p(x)){

      a = i*(int)Math.pow(-1, i);
      i++;
      x+=a;
    }

    System.out.println( (int) Math.abs(x-z));}

это для n>=2.


в python:

>>> def nearest_prime(n):
    incr = -1
    multiplier = -1
    count = 1
    while True:
        if prime(n):
            return n
        else:
            n = n + incr
            multiplier = multiplier * -1
            count = count + 1
            incr = multiplier * count

>>> nearest_prime(3)
3
>>> nearest_prime(4)
3
>>> nearest_prime(5)
5
>>> nearest_prime(6)
5
>>> nearest_prime(7)
7
>>> nearest_prime(8)
7
>>> nearest_prime(9)
7
>>> nearest_prime(10)
11

<?php
$N1Diff = null;
$N2Diff = null;

$n1 = null;
$n2 = null;

$number = 16;

function isPrime($x) {

    for ($i = 2; $i < $x; $i++) {
        if ($x % $i == 0) {
            return false;
        }
    }

    return true;
}


for ($j = $number; ; $j--) {

    if( isPrime($j) ){
       $N1Diff = abs($number - $j);
       $n1 = $j;
       break;
    }
}


for ($j = $number; ; $j++) {

    if( isPrime($j) ){
       $N2Diff = abs($number - $j);
       $n2 = $j;
       break;
    }

}

if($N1Diff < $N2Diff) {

    echo $n1;

} else if ($N1Diff2 < $N1Diff ){
    echo $n2;
}

Если вы хотите написать алгоритм, поиск в Википедии простое число привел меня к другой статье о решето Эратосфена. Алгоритм выглядит немного простым, и я думаю, что рекурсивная функция подойдет ему хорошо imo. (Тут я могу ошибаться.)


Если решение массива не является допустимым решением для вас (это лучшее решение для вашего сценария), вы можете попробовать код ниже. После случая "2 или 3"он будет проверять каждое нечетное число от начального значения, пока не найдет простое.


static int NearestPrime(double original)
{
    int above = (int)Math.Ceiling(original);
    int below = (int)Math.Floor(original);

    if (above <= 2)
    {
        return 2;
    }

    if (below == 2)
    {
        return (original - 2 < 0.5) ? 2 : 3;
    }

    if (below % 2 == 0) below -= 1;
    if (above % 2 == 0) above += 1;

    double diffBelow = double.MaxValue, diffAbove = double.MaxValue;

    for (; ; above += 2, below -= 2)
    {
        if (IsPrime(below))
        {
            diffBelow = original - below;
        }

        if (IsPrime(above))
        {
            diffAbove = above - original;
        }

        if (diffAbove != double.MaxValue || diffBelow != double.MaxValue)
        {
            break;
        }
    }

    //edit to your liking for midpoint cases (4.0, 6.0, 9.0, etc)
    return (int) (diffAbove < diffBelow ? above : below);
}

static bool IsPrime(int p)  //intentionally incomplete due to checks in NearestPrime
{
    for (int i = 3; i < Math.Sqrt(p); i += 2)
    {
        if (p % i == 0)
            return false;
    }

    return true;
}

таблица поиска с размером 100 байт; (беззнаковые символы) Круглое реальное число и используйте таблицу поиска.


самый простой ответ- Каждое простое число может быть представлено в виде (6*x-1 и 6 * X +1) (кроме 2 и 3). пусть число N. разделите его на 6. t=N / 6; сейчас a=(t-1)*6 b=(t+1)*6 и проверить, какой из них ближе к Н.