Эта программа на C17 проверяет числа пробным делением и перечисляет простые числа от 1 до верхней границы n включительно. Простое число — целое число не меньше 2, поэтому при границе 0 или 1 простые числа не выводятся. Введите одно десятичное целое число от 0 до INT_MAX.
Код
| |
Компиляция и пример запуска
Сохраните программу в primes.c. В среде с GCC выполните gcc -std=c17 -Wall -Wextra -O2 primes.c -o primes, затем ./primes. При вводе 30 после заголовка появится строка:
| |
При границе 2 выводится 2, при 0 или 1 — пустая строка. Ввод читается как одна текстовая строка длиной не более 127 байтов без символа новой строки. Допускаются пробельные символы в начале и конце, а также начальный знак +. Отрицательные значения, пустые строки, текст, не представляющий целое число, значения вне диапазона, слишком длинные строки и ошибки чтения приводят к сообщению об ошибке и завершению программы. Обрабатывается только первая строка; последующие не используются.
Как работают проверка и обработка ввода
isPrimeвозвращает ложь для значений не больше 1 и истину для 2 и 3. Для остальных чисел, кратных 2 или 3, возвращается ложь. Затем проверяютсяiиi + 2приi = 5, 11, 17, .... Возможные делители имеют вид6k - 1или6k + 1; это не числа, кратные 6. При этом не каждое число такого вида является простым.- У каждого составного числа есть простой делитель, не превосходящий его квадратного корня. Поэтому достаточно проверять, пока
i <= num / i. Для положительных целых чисел это тот же диапазон, что и приi * i <= num, но без переполнения умножения в типеint. Вычислять квадратный корень с плавающей точкой не требуется. printPrimesвыводит только пустую строку, если граница меньше 2. Иначе сначала выводит 2, затем проверяет нечётные кандидаты. Приi > n - 2цикл завершается до сложения, что предотвращает переполнение последнегоi += 2, даже если граница равнаINT_MAX.readLimitчитает ввод черезfgets, проверяет указатель конца преобразования иERANGEотstrtol, а также диапазон от 0 доINT_MAXперед преобразованием вint. Аргументisspaceпредварительно преобразуется вunsigned char. Игнорирование возвращаемого значенияscanf("%d", &n)может привести к использованию неинициализированногоnпосле неудачного ввода. Нельзя также предполагать, что результат преобразования за пределами диапазонаintбудет обработан как обычная ошибка преобразования.
Область применения
INT_MAX зависит от реализации. Для 32-битного int он равен 2,147,483,647, но C не требует этого значения для всех реализаций. Возможность представить границу не означает, что все простые числа до неё можно быстро вывести.
Это реализация для изучения пробного деления. При проверке одного числа количество делений сверху ограничено величиной, пропорциональной его квадратному корню. Для перечисления всех кандидатов грубая верхняя оценка составляет O(n sqrt(n)) делений. Здесь одно деление считается одной операцией; это не битовая сложность и не измеренное время работы. Для перечисления простых чисел в большом диапазоне стоит рассмотреть решето Эратосфена. Программа не является генератором криптографических простых чисел. О проверке больших целых чисел см. статью о тесте Миллера—Рабина.
Правила функций ввода и целочисленной арифметики C приведены в разделах 6.5, 7.4, 7.21.6.2, 7.21.7.2 и 7.22.1.4 комитетского проекта C11 N1570 рабочей группы WG14.
