Какой алгоритм можно использовать для проверки, является ли число простым?

Недавно я услышал определение простого числа и решил написать функцию для его проверки. Однако, столкнулся с проблемой: при очень больших числах время перебора становится значительным. Существует ли способ сократить количество итераций при проверке числа, например, 1000000? 

```javascript
function checkForPerfectNumber(num) {
  const numbers = [];
  
  for(let i = 1; i < num; ++i) {
    const rest = num % i;
    if(!rest) numbers.push(i);
  }
  
  const count = numbers.reduce((acc, val) => acc + val, 0);
  
  return count === num;
}
```
  • 12 февраля 2025 г. 13:04
Ответы на вопрос 3
Для проверки, является ли число простым, существует несколько методов, которые могут значительно сократить количество итераций по сравнению с простым перебором всех чисел от 1 до n. Вот один из наиболее эффективных подходов:

### Алгоритм проверки на простоту

1. **Обработка специальных случаев**:
   - Если число меньше 2, оно не простое.
   - Числа 2 и 3 являются простыми.
   - Если число четное и больше 2, оно не простое.

2. **Проверка делителей**:
   - Можно проверять делимость только до квадратного корня из числа. Если число `n` не делится на какое-либо число до `sqrt(n)`, то оно простое.
   - Достаточно проверять только нечетные числа, начиная с 3 (после предварительной проверки 2).

### Пример реализации в JavaScript

Вот функция, которая проверяет, является ли число простым:

```javascript
function isPrime(num) {
    // Обработка специальных случаев
    if (num <= 1) return false;
    if (num <= 3) return true;
    if (num % 2 === 0 || num % 3 === 0) return false;

    // Проверяем делители до квадратного корня числа
    for (let i = 5; i * i <= num; i += 6) {
        if (num % i === 0 || num % (i + 2) === 0) {
            return false;
        }
    }
    return true;
}

// Примеры использования
console.log(isPrime(1)); // false
console.log(isPrime(2)); // true
console.log(isPrime(3)); // true
console.log(isPrime(4)); // false
console.log(isPrime(29)); // true
console.log(isPrime(1000000)); // false
```

### Объяснение:

1. Начинаем с проверки специальных случаев.
2. Используем цикл для проверки делителей, начиная с 5 и проверяем через 6 (проверяем `i` и `i + 2`), так как все простые числа, кроме 2 и 3, имеют вид `6k ± 1`.
3. Цикл выполняется, пока `i * i <= num`, что позволяет значительно сократить количество проверок по сравнению с проверкой всех чисел до `num`.

Этот алгоритм будет работать эффективно даже для относительно больших чисел, например, до 10 миллионов и выше, в зависимости от вычислительных возможностей вашей системы.
Если нужно проверить а) точно, и б) одно; в) не очень большое число (миллион тоже небольшое) — ничего нет лучше, чем проверка нечётных чисел до корня из n. То есть до 1000. 

Если точно, много и небольшие — то придётся держать список простых чисел, пополняя его, когда попадётся слишком большое число. Список тоже до корня из n. Допустим, если предел — int4 (≈4 млн), то нужно держать только список до 65535, это пара тысяч чисел.

Если число совсем небольшое и может быть где-то в списке — ищем его хитрой разновидностью поиска: проверяем 1-е число, 2-е, 4-е и т.д., пока не определим диапазон, где может быть число. И в этом диапазоне ищем двоичным поиском.

В криптографии востребован неточный поиск — «число, скорее всего, простое». Но об этом не будем, вы не настолько круты. Тут уже основано на том, что держим таблицу небольших простых чисел и делим на них, а затем гоняем неточные тесты.

PERFECT number — это СОВЕРШЕННОЕ число. Это не то (сумма всех делителей равняется самому числу), и для теста на совершенное число тоже надо проверять до корня из n — если a делится на b, то добавляем и b, и a/b (кроме случаев, когда b=1 и b²=a, разумеется). Если есть простые числа до корня из n — тоже можно разбить на простые множители (один из множителей может быть больше корня из n!) и подключить комбинаторику, чтобы заполучить остальные.
Похожие вопросы