Здесь я хотел бы сказать несколько слов о том, как трудно решить, является ли заданное число простым.
Вальтер Боро. Дружественные числа. Открытая лекция, пропитанная при вступлении в должность в Боннском университете
Пожалуй, здесь не будет лишним отметить ошибочность довольно распространенного мнения, будто данная тема — занятие, подходящее лишь для тупых вычислителей, а для настоящих математиков слишком скучное.
Вальтер Боро. Дружественные числа. Открытая лекция, прочитанная при вступлении в должность в Боннском университете
В предыдущей главе, разлагая числа на простые множители, нам уже приходилось проверять числа на простоту. Как вы помните, для этого служит функция
PrimeQ, название которой заканчивается прописной буквой Q (question — вопрос), что означает, что она в качестве значения выдает
True или False. Числа, ассоциированные с 1 (например, 1 и -1), она к простым не относит.
PrimeQ[5] True
PrimeQ[5+0 I] True
PrimeQ[5,Gaussianlntegers-XTrue] False
M[n_]=2An-l;
Do[If[PrimeQ[M[n]],Print[n,","}], {n,5000}]
В системе Mathematica имеется также множество (область) простых чисел Primes. Его также можно использовать для проверки простоты числа. Нужно просто проверить, принадлежит ли число этому множеству. Убедимся, например, что число 1234567 составное.
1234567€Primes False
Иногда нужно не только знать, простое или составное данное число, но и иметь доказательство (или опровержение) его простоты. Конечно, система Mathematica не пишет развернутый текст такого доказательства (или опровержения), но она может выдать систему чисел, доказывающую (или опровергающую) простоту заданного числа. Такая система чисел называется свидетельством, или сертификатом. Что может быть сертификатом? В принципе это зависит от "внутренней кухни" той системы, которая генерирует сертификат. В случае составного числа можно указать, например, его нетривиальный делитель. При составном числе n можно также указать такое а, для которого не выполняется сравнение
an-1 =1(modn). Система Mathematica для установления простоты числа использует теорию эллиптических кривых. Основанный на ней алгоритм, придуманный Аткином (Atkin), Голдвассером (Goldwasser) и Кильяном (Kilian), является в настоящее время наилучшим, если не принимать во внимание квантовых компьютеров, пока еще не реализованных. Этот алгоритм подробно описан в статье Atkin А. О. L. and Morain F. Elliptic Curves and Primality Proving (Mathematics of Computation, 1993, pp. 29-68). Однако он довольно сложен, и в настоящее время даже не все студенты-математики изучают его (как и теорию эллиптических кривых). Поэтому пользуются им чаще всего профессионалы. Тем не менее в отдельных случаях такой сертификат вполне понятен и для школьника. Вот пример. Вызвав функцию
PrimeQCertificate[3837523], получим сертификат {2, 3837522, 3837523}, который показывает, что 238"522(mod3837523) не равно 1. (Сертификаты, опровергающие простоту, легко распознать: они всегда состоят из трех чисел.)
В пакете теории чисел (загружается по команде <<NumberTheory'NumberTheory-Functions') имеются две чрезвычайно полезные функции, значениями которых являются простые числа.
Функция PreviousPrime [n] генерирует наибольшее простое число, меньшее n. Если n не больше 2, будет сгенерировано отрицательное простое число.
PreviousPrime[1]
-2
PreviousPrime[2 ]
-2 PreviousPrime[-72]
-73 PreviousPrime[1ООО]
997
Функция NextPrime[n] генерирует наименьшее простое число, большее n.
NextPrime[-1000]
-997
NextPrime[-l]
2
NextPrimeflOOO]
1009 NextPrime[1009]
1013
Иногда нужно сгенерировать какое-нибудь случайное простое число, лежащее в заданном интервале. Для этого используется конструкция Random [Prime, {n, m}]. Вот несколько примеров ее использования.
Random[Prime,{10^6,10^12}]
837590772197 Random[Prime,{10^6+0.5,10^12}]
924457361921
Как известно, треугольники, у которых длины двух сторон выражаются целыми числами, называются пифагоровыми. Хорошо известно, что длина ни одной из сторон пифагорового треугольника не может быть равна 2. Поэтому у пифагоровых треугольников длины сторон могут выражаться только нечетными простыми числами. А потому длина хотя бы одной из сторон пифагорова треугольника должна быть четной (по теореме Пифагора) и потому выражается составным числом. (Составным потому, что четным, отличным от 2.) Боле того, несложно доказать, что если р и q — длины сторон пифагорова треугольника, выражающиеся простыми числами, то
р2 = 2q -1.
И наоборот, если существуют такие простые числа р и q, что р2 = 2q - 1, то в прямоугольном треугольнике с гипотенузой q и катетом р второй катет равен
√q2 - р2 = q -1 ,
и потому такой треугольник будет пифагоровым. Для нахождения пифагоровых треугольников, у которых длины двух сторон выражаются простыми числами, можно применить функции
PrimeQ и NextPrime. Область поиска ограничим теми треугольниками, у которых меньший катет р не превосходит заданного числа п. Достаточно найти длину меньшего катета р и длину гипотенузы q, поскольку длина второго катета на единицу меньше длины гипотенузы: q-1
Порядок использования этой функции такой: сначала загрузить пакет теории чисел, а затем ввести это определение. Только после этого можно ее вызвать.
PythagorasTriangles[10000]
Результаты удобно отформатировать в виде таблицы .
Как видно из таблицы, таких треугольников совсем немного. Интересно, сколько же таких треугольников, у которых длина меньшего катета выражается не более чем n-значным числом? Давайте посчитаем. Вот нужная нам функция, которая печатает свой аргумент п, двоеточие : и количество найденных ею треугольников, меньший катет которых не превосходит n.
Теперь можем выполнить вычисления.
Do[NumberOfPythagorasTriangles[10^n],{n,9}]
Результаты отформатируем в виде таблицы.
Студент на экзамене: Чтобы составить таблицу простых чисел, нужно трясти решето. Преподаватель: Сколько раз? Студент: Ну, пока не вытрясется все лишнее.
Мехматовский фольклор
В предыдущей главе, разлагая числа на простые множители, мы опустили вопрос о том, как составляются таблицы простых чисел. Тем не менее этот вопрос интересовал еще древних греков, и Эратосфен изобрел решето, пользоваться которым умеет каждый пятиклассник. Однако обычно незачем заниматься столь утомительным занятием: в необходимых случаях система Mathematica изготовляет это самое решето и трясет его сколько надо. Пользователю же предоставляется функция
Prime [n], которая возвращает n-е простое число рn. Поэтому, чтобы построить таблицу первых 100 простых чисел, достаточно одной команды.
Несложно построить и график первых ста простых чисел.
Но что делать, если нужно построить таблицу не от начала, а только ее часть, скажем
Рn , Рn+1,... Рn+m ? Ничего страшного, вот пример.
Здесь построена таблица простых чисел р10^12+1, р10^12+2,
..., p10^12+100. И уж конечно не составляет труда вычисление отдельного простого числа
рn по его номеру n.., если только n не слишком велико. Вот примеры.
Но если n очень велико, система Mathematica откажется вычислять Prime [n].
В таких случаях вам придется решать, что делать: строить решето или использовать другие методы. Говорят, впрочем, что верхнюю планку для аргумента
n функции
Prime [n] скоро поднимут примерно до 260... Не слишком высоко, до бесконечности еще идти и идти, но даже того, что есть, более чем достаточно для классических учебников (и задачников) по теории чисел.
За одним-единственным исключением pn =2, р2 = 3, числа рn и рn+1 не являются смежными в натуральном ряду. Еще Евклид знал, что существуют сколь угодно длинные отрезки натурального ряда, целиком состоящие из составных чисел. Как же найти отрезок натурального ряда, целиком состоящий из составных чисел? Для этого полезно определить следующую функцию.
Вот как ее можно использовать. CompositeRuns/@Range[10]
Здесь она запускается 10 раз. Вот что получится (вывод немного отформатирован).
{4},
8,9},
8,9,10},
24,25,26,27},
24,25,26,27,28},
90,91,92,93,94,95} ,
90,91,92,93,94,95,96},
114,115,116,117,118,119,120,121},
114,115,116,117,118,119,120,121,122},
114,115,116,117,118,119,120,121,122,123}}
CompositeRunsStart[n_Integer?Positive]:=Block[{pi,p2=3,i=2},
While[(pi,p2}={p2,Prime[++i]};
p2-pl<n+l];Print[{n,pl-H}]]
{1,4}
{3,8}
{5,24}
{7,90}
{13,114}
LargestPrimeGap[n_Integer?(#<3&)]:=
Max[Drop[f,1]-Drop[#,-1]&[Prime/@Range[2,PrimePi[n]]]]
{3,2}
{4,4}
{5,6}
(6,6}
{7,14}
{8,14}
{9,14}
{10,20}
{11,34}
{12,34}
{13,34}
{14,44}
{15,72}
{16,72}
{17,72}
{18,86}
{19,114}
{20,114}
{21,148}
{22,148}
{23,154}
{24,154}
{25,210}
{26,220}
{27,222}
{28,248}
{2,2}
{3,4}
{4,6}
{5,14}
{6,14}
{7,20}
{8,34}
{9,34}
{10,52}
{11,72}
{12,86}
{13,112}
{14,114}
{15,148}
{16,154}
{17,210}
{18,220}
{19,222}
{2,2}
{3,4}
{4,6}
{5,14}
{6,18}
{7,34}
{8,34}
{9,52}
{10,72}
{11,86}
{12,114}
{13,132}
{14,154}
{15,154}
{16,210}
{17,222}
base=5;Do[Print[{n,LargestPrimeGap[bаsе^n]}],
{n,2,17}] {2,4}-{3,8} {4,18} {5,34}
{6,36} {7,72} {8.,112} {9,132} {10,154}
{11,220} {12,248}
No more memory available.
Mathematica kernel has shutdown.
Try quitting other applications and then retry.
Рис. 5.1. Вот как растет файл подкачки
Хотя мы и получили довольно интересные результаты, завершение вычислений было несколько неожиданным. Давайте попробуем с основанием 7.
base=7;Do[Print[{n,LargestPrimeGap[bаsе^n]}],
{n,2,15}] {2,6} {3,14} {4,34} {5,44}
{6,72} {7,114} {8,154} {9,210}
Рис. 5.2. Отчетливо видно плато Высокой производительности, рассеченное, правда, Каньоном вспомогательных действий. Плато Высокой производительности имеет почти отвесные обрывы
Наконец, проведем вычисления для основания, равного 10.
base=10;Do[Print[{n, LargestPrimeGap[base^n]}],{n,2,12}]
{2,8}
{3,20}
{4,36}
{5,72}
{6,114}
{7,154}
{8,220}
No more memory available.
Mathematica kernel has shut down.
Try quitting other applications and then retry.
Рис. 5.3. Отчетливо видно не только плато Высокой производительности, но и почти отвесный обрыв Холма увеличения файла подкачки, связанный с завершением работы системы Mathematica
У всякой истории есть мораль, и эта не исключение. Некоторые функции, даже если они описаны в справочной системе (именно оттуда я взял функцию LargestPrimeGap), иногда требуют неоправданно большого объема памяти. Недостаточный объем памяти может помешать получить нужные результаты. Даже ночной прогон в таких случаях не помогает.
Давайте посмотрим, можно ли исправить ситуацию. Сначала загрузим пакет теории чисел.
<<NumberTheory`NumberTheoryFunctions`
Теперь определим функцию LargestPrimeGap01.
LargestPrimeGap01[n_]:=
Block[(pl=2,p2=3,i=2,pk=PreviousPrime[n+1],d=Max[n-pk,1]},
Whilefp2<pk,{pl=p2;
p2=NextPrime[p2];delta=p2-pl;
If[delta>d, d=delta]}];d]
base=10;Do[Print[{n, LargestPrimeGap01[bаsе^n]}},
{n,2, 9}] {2,8} {3,20} {4,36} {5,72}
{6,114} {7,154} {8,220} {9,282}
Рис. 5.4. Отчетливо видно, что файл подкачки не растет, а загрузка ЦП не падает ниже 50% несмотря ни на какие переключения задач
В теории чисел длина наибольшего из интервалов между 1 и х, не содержащих простых чисел, обычно обозначается через g(x). Например, g(200) = 14, поскольку самым длинным таким интервалом при х=200 является интервал от 113 до127. Как мы видели, величина g(x) растет очень неравномерно, однако некоторые эвристические соображения, подкрепленные статистическими данными, приводят к асимптотической формуле g(x)~(lnx)2. Давайте все-таки проверим на графике, насколько хорошо
согласуется с ожидаемым поведением эта чрезвычайно скачущая функция. Сначала нарисуем график на интервале (1, 1000).
Похоже мало, но неплохо бы уточнить.
Вот еще одно уточнение.
И, наконец, нарисуем график на интервале (1,1 000 000).
Конечно, похоже. Но не более, чем статистика на правду...
Пример 5.9. График разностей между последовательными простыми числами.
Давайте теперь построим график разностей между последовательными простыми числами. Сначала мы используем функции Table и Prime для построения таблицы t1 (точнее, списка) первых n простых чисел.
t1= Tablet Prime[k],{k,1,n=10Л5}];
Теперь составим таблицу t2 (тоже список) разностей между последовательными простыми числами.
t2=Table[t1[[i+1]]-t1[[i]], {i,1,Length[t1]-1}];
Наконец, мы можем использовать функцию ListPlot для построения графика.
А вот график для n = 10000.
Изучая распределение простых чисел, мы узнали, что интервалы, состоящие из составных чисел, могут быть сколь угодно длинными. Однако встречаются и очень короткие интервалы, ограниченные простыми числами. Простые числа 2 и 3 следуют друг за другом, не пропуская между собой ни одного составного числа. Но это, конечно, исключение, больше нигде не встречающееся в натуральном ряду. Но зато немало встречается таких пар простых чисел, между которыми стоит только одно составное число (четное, естественно). Простые числа, разность которых равна 2, называются близнецами. Честно говоря, это наименьшая возможная разность между нечетными простыми числами. (Потому что все простые числа, за исключением 2, нечетны!) Вот как определяется функция, которая отыскивает все пары близнецов среди первых т простых чисел.
TwinPrimes[m_]:=
Module[{s=Prime[Range[m]]},
{#,#+2}&/@Extract[s,Position[Dropfs,1]-
Drop[s,-l],2]]]
В ряде областей науки и техники, например в теории кодирования, важно знать простые числа, близкие к числам определенного вида (чаще всего к степеням таких оснований, как 2, 3 и 10). Вне сомнения, их можно было бы найти в обычных таблицах простых чисел. Однако таблицы нужного размера не могли бы поместиться даже в многотомных изданиях. Поэтому существуют специальные таблицы, в которых приводятся только простые числа, близкие, например, к 2n, 3n и 10n.
Но составить такие таблицы для достаточно больших n довольно трудно, и, несмотря на компактность, такие таблицы зачастую весьма неполны. С помощью системы Mathematica несложно составить такие таблицы самостоятельно. Допустим, таблица должна содержать десять наибольших простых чисел, предшествующих N, и десять простых чисел, следующих за N. Можно ограничиться случаем достаточно больших N, например N>1000, поскольку при меньших N вопрос решается с помощью таблиц простых чисел, помещаемых обычно в учебниках для пятиклассников.
Давайте попытаемся составить нужную нам программу, например, для степеней 10. Чтобы результаты выглядели наглядно, нужно предусмотреть их преобразование в таблицу с помощью текстового процессора, например, Word. Поэтому необходимо предусмотреть такой формат результатов, который было бы легко отформатировать (преобразовать в таблицу). Для этого можно предусмотреть двоеточие : в качества разделителя колонок и два двоеточия : : в качестве разделителя строк таблицы. Вот как может выглядеть программа.
В этой программе использованы функции PreviouskPrimes и NextkPrimes. Функция PreviouskPrimes [N, k] должна генерировать k наибольших простых чисел, меньших Ж Иными словами, она должна генерировать k простых чисел, предшествующих N. Функция NextkPrimes [N, k] должна генерировать k наименьших простых чисел, больших N. Иными словами, она должна генерировать k простых чисел, следующих за N. Вот и все. Нам осталось только написать код этих двух функций. Давайте начнем с функции PreviouskPrimes [N, k].
PreviouskPrimes[n_Integer?(#>100&)
, k_Integer?Positive]:=
Block[{p=PreviousPrime[n] , i=l},
While[i<=k,
{Print[p,","],
p=PreviousPrime[p],++i}]]
NextkPrimes[n_Integer?(#>100&) ,
k_Integer?Positive]: = Block[{p=NextPrime[n],i=l},
While[i<=k,{Print[p,","],
p=NextPrime[p] , + + i} ]]
PreviouskPrimes[n_Integer?(#>100&),
k_Integer?Positive]:= Block[{p=PreviousPrime[n],i=l},
While[i<=k,(Print[p,","],
p=PreviousPrime[p]/++i}]]
PreviouskPrimes[1000,3]
997 ,
991 ,
983 ,
NextkPrimes[n_Integer?(#>100&),
k_Integer?Positive]:= Block[{p=NextPrime[n],i=l},
While[i<=k, {Print[p,","],p=NextPrime[p],++i} ]]
NextkPrimes[1000,3]
1009 ,
1013 ,
1019 ,
6 : <
999983 999979 999961 999959 999953
999931 999917 999907 999883 999863
1000003 1000033 1000037 1000039
1000081 1000099 1000117 1000121 1000133 1000151
7 :
9999991 ,
9999973 ,
9999971 ,
9999943 ,
Согласитесь, изучив все тонкости искусства составления таблиц простых чисел, было бы нелогично пренебречь искусством составления таблиц на основе уже созданных. Почему бы, имея полную (значит, бесконечную!) таблицу простых чисел, не поинтересоваться, сколько чисел в этой таблице не превосходят данного числа х. Иными словами, определить число простых чисел, не превосходящих х. Это число в учебниках теории чисел обозначается л(х). Функция п(х) привлекала внимание уже античных математиков. Евклид, например, установил, что она неограниченно возрастает с ростом аргумента. Изучением этой функции занимались почти все великие математики Прошлого, ее исследовали Лежандр, Чебышев, Риман, Адамар, Валле-Пуссен, Чудаков, Виноградов, Коробов, Литлвуд, Сельберг, Эрдеш, Ингам, Прахар, Пан Чен-тонг, Чен-ин-рун, Титчмарш, Мейссель, Рогель, Чипола, Мертенс, Гаусс, Бертран, Вейль, Линник, Бомбьери...
В системе Mathematica эта функция называется PrimePi. Система Mathematica может вычислить ее значения практически в мгновение ока... Правда, не все.
В документации, правда, верхний предел указан примерно равным 260, а на самом деле...
Тем не менее не следует воспринимать ситуацию уж очень пессимистически. Давайте, например, построим графики функций на промежутке (0, 100).
Как видите, если не считать неприятностей с нулем, где . Впрочем, вот график с интегральным логарифмом.
Теперь даже в нуле неприятностей нет. Но вот вопрос: будет ли заметна ступенчатость на больших интервалах? На самом деле ступенчатость незаметна уже на интервале (0, 10000).
Но какая же функция приближает или Li(x)? Конечно, Li(x).
Если же построить график на интервале (0, 10000), то графики
Раз уж речь зашла о приближении k(х), давайте построим графики разности функции (приближение Чебышева и Лежандра), в качестве второй — 1л(х) (приближение Гаусса), а в качестве третьей — R(x) (приближение Римана). Сначала определим функцию R(x).
Riemann[x_]:=
Last[Block[{R=LogIntegral[x],y=LogIntegral[Sqrt[x]]/2,n=2},
{While[y>0.000000001,{R=R-y; n=n+l;y=LogIntegral[х^(1/n)]/n}
],R} ]]
С помощью функции PrimePi несложно подсчитать и количество простых чисел на открытом слева отрезке (а, b]. Помните только, что если вы пользуетесь выражением k(b)-n(а), т.е. выражением PrimePi [b] -PrimePi [a], то в случае простоты простое число b будет посчитано, а простое число а — нет. Иными словами, подсчет осуществляется на открытом слева отрезке (а, b]. А что, если нужно посчитать простые числа на замкнутом с обоих концов отрезке [а, b}1 Ничего сложного: в качестве аргумента можно взять не а, а несколько меньшее число, ведь аргументом функции PrimePi может быть любое вещественное положительное число. Давайте посчитаем, например, количество простых чисел в 1-й, 2-й, ... , 20-й сотне миллионов натуральных чисел. Вот как это можно сделать.
delta=100000000;
PrimePiAB[delta_Integer?Positive,xk_Integer?Positive]:=
Block[{k=0, x=delta, kt=0 },
While[x<=xk,
{kt=PrimePi[x];
Print[x,":",kt,":",kt-k];
k=kt; x=x+delta}]]
PrimePiAB[delta,10 delta]
DeltaPi[x_,delta_]:=
Block[{xk=x+delta,k=PrimePi[xk]},
Print[x,"-",xk,":",k-PrimePi[x]]]