Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Mathematica 5. ╨б╨░╨╝╨╛╤Г╤З╨╕╤В╨╡╨╗╤М

.pdf
Скачиваний:
1
Добавлен:
19.11.2023
Размер:
33.75 Mб
Скачать

его нетривиальный делитель. При составном числе п можно также указать такое а, для которого не выполняется сравнение а" 1=l(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}, ко­ торый показывает, что 238375"(mod3837523) не равно 1. (Сертификаты, опровергающие

простоту, легко распознать: они всегда состоят из трех чисел.)

функции PreviousPrime и NextPrime

ислучайные простые числа

Впакете теории чисел (загружается по команде «NumberTheory 'NumberTheoryFunctions') имеются две чрезвычайно полезные функции, значениями которых яв­ ляются простые числа.

Наибольшее простое число, меньшее л, — PreviousPrime[n]

Функция PreviousPrime [п] генерирует наибольшее простое число, меньшее п. Если п не больше 2, будет сгенерировано отрицательное простое число.

PreviousPrime[1]

-2

PreviousPrime[2]

-2

PreviousPrime[-72]

-73

PreviousPrime [1000].

997

Функция PreviousPrime [n] работает относительно быстро даже для большого аргумента.

PreviousPrime[2 А1 2 8 ] //Timing

{0. Second,340282366920938463463374607431768211297} PreviousPrime[2 А2 5 6 ] //Timing

{0.031 Second,

1157920892373161954235709850086879078532699846656405640394575840079131

29639747}

PreviousPrime[2 A1 0 0 0 ] //Timing

{1.891 Second,

1071508607186267320948425049060001810561404811705533607443750388370351

0511249361224931983788156958581275946729175531468251871452856923140435

9845775746985748039345677748242309854210746050623711418779541821530464

7498358194126739876755916554394607706291457119647768654216766042983165

2624386837205668068131}

Арифметика: простые числа

141

Наименьшее простое число, большее л, — NextPrime[n]

Функция NextPrime [п] генерирует наименьшее простое число, большее п.

N e x t P r im e [-1000] -997

N e x t P r im e [-1 ]

2

N e x t P r im e [1000] 1009

N e x t P r im e [1009] 1013

Функция NextPrime [n] работает относительно быстро даже для большого аргу­ мента.

NextPrime[1 0 А2 0 ] //Timing

{ 0 .0 1 6 S e c o n d ,100000000000000000039} NextPrime[10А50]//Timing

{0 .0 1 6 S e c o n d ,100000000000000000000000000000000000000000000000151}

NextPrime[10A1 0 0 ] //Timing

{0 .0 6 2 Second, 1000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000267} NextPrime[10A2 0 0 ] //Timing

{ 0 .3 7 5 Second, 1000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000357} NextPrime[10A5 0 0 ] //Timing

{ 3 .6 0 9 Second, 1000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000000

0000000000000000000000000000000000000000000000000000000000000000000000

00000000961}

Случайное простое число в заданном интервале —

Random[Prime, {n, т}]

Иногда нужно сгенерировать какое-нибудь случайное простое число, лежащее в заданном интервале. Для этого используется конструкция Random[Prime, {n, m }]. Вот несколько примеров ее использования.

Random[Prime,{10А6,10А12}] 837590772197

R andom [Prim e,{10А6 + 0 . 5 , 10А1 2 }]

924457361921

Конечно, если в указанном интервале простых чисел нет, будет сгенерировано предупреждение. Вот пример некорректного вызова.

R andom [Prim e,{1 0 А6 + 0 . 5 ,1 0 А6+2}]

Random::noprime: There are no primes in the specified interval.

142

Глава 5

Random::randt

Type specification

Prime

in Random [Prime,

{«13»,

1 « 5 »

2}]

should be

Real,

Integer,

or Complex. More...

Random [Prime , {1.x 106, 1000002 }]

 

Пифагоровы треугольники, у которых длины двух сторон

выражаются простыми числами

Как известно, треугольники, у которых длины двух сторон выражаются целыми числами, называются пифагоровыми. Хорошо известно, что длина ни одной из сторон пифагорового треугольника не может быть равна 2. Поэтому у пифагоровых треуголь­ ников длины сторон могут выражаться только нечетными простыми числами. А пото­ му длина хотя бы одной из сторон пифагорова треугольника должна быть четной (по теореме Пифагора) и потому выражается составным числом. (Составным потому, что четным, отличным от 2.) Боле того, несложно доказать, что если р и q — длины сто­

рон пифагорова треугольника, выражающиеся простыми числами, то p2 = l q - \ .

И наоборот, если существуют такие простые числа р и q, что р1= 2q - 1 , то в прямо­

угольном треугольнике с гипотенузой q и катетом р второй катет равенy]q2 - р2 —q - \ ,

и потому такой треугольник будет пифагоровым. Для нахождения пифагоровых тре­ угольников, у которых длины двух сторон выражаются простыми числами, можно применить функции PrimeQ и NextPrime. Область поиска ограничим теми треуголь­ никами, у которых меньший катет р не превосходит заданного числа п. Достаточно найти длину меньшего катета р и длину гипотенузы q, поскольку длина второго катета на единицу меньше длины гипотенузы: q—1.

PythagorasTriangles [n_] :=

Block[{p=2,i=0},

While[p<n,

{q=(рЛ2+1)/2;

If[PrimeQ[q],

{++i;Print [i,":",p, ":",q-1 ,":",q] }];p=NextPrime [p] }]]

Порядок использования этой функции такой: сначала загрузить пакет теорйи чи­ сел, а затем ввести это определение. Только после этого можно ее вызвать.

PythagorasTriangles[10000]

Результаты удобно отформатировать в виде таблицы (табл. Б. 19).

Как видно из таблицы, таких треугольников совсем немного. Интересно, сколько же таких треугольников, у которых длина меньшего катета выражается не более чем л-значным числом? Давайте посчитаем. Вот нужная нам функция, которая печатает свой аргумент п, двоеточие и количество найденных ею треугольников, меньший катет которых не превосходит п.

NumberOfPythagorasTriangles[n_]:= Block[{p=2,i=0},

{While[p<n,

{q=(рЛ2+1)/2;

If[PrimeQ[q], ++i];p=NextPrime[p]}; ];Print [n, ":”,i] }]

Теперь можем выполнить вычисления.

Do[NumberOfPythagorasTriangles[10Лп],{n,9}]

Результаты отформатируем в виде таблицы (табл. Б.20).

Арифметика: простые числа

143

Таблицы простых чисел

Студент на экзамене: Чтобы составить таблицу простых чисел, нужно трясти решето.

Преподаватель: Сколько раз?

Студент: Ну, пока не вытрясется все лишнее.

Мехматовский фольклор

Функция Prime[n] — п-е простое число р„

В предыдущей главе, разлагая числа на простые множители, мы опустили вопрос о том, как составляются таблицы простых чисел. Тем не менее этот вопрос интересовал еще древних греков, и Эратосфен изобрел решето, пользоваться которым умеет каж­ дый пятиклассник. Однако обычно незачем заниматься столь утомительным занятием: в необходимых случаях система Mathematica изготовляет это самое решето и трясет его сколько надо. Пользователю же предоставляется функция Prime [п], которая воз­

вращает л-e простое число рп. Поэтому, чтобы построить таблицу первых 100 про­

стых чисел, достаточно одной команды.

Table[Prime[n],{n,100}]

{2,3,5,7,11,13,17,19,23, 29, 31,37,41/ 43, 47,53, 59, 61, 67,71,73,7 9,83,89, 97,101,103,107,109/113,127,131,137,139,149,151,157,163,167,173,179, 181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271, 277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379, 383,389, 397,401,409, 419, 421,431,433, 439, 443, 449, 457,4 61,4 63; 467,47 9, 487,491,499,503,509,521,523,541}

Несложно построить и график первых ста простых чисел.

ListPlot[Table[Prime[n],{n,100}]]

500

400

300

200

100

20

40

60

80

100

Но что делать, если нужно построить таблицу не от начала, а только ее часть, скажем р„ , рпП, рпш ? Ничего страшного, вот пример.

Prime [Range [1012 + 1 , 1012 + 100] ]

{29996224275851,29996224275883,29996224275907,29996224275917,'

29996224275937,29996224275973,29996224276009,29996224276019,

29996224276021,29996224276091,29996224276097,29996224276153,

29996224276231,29996224276309,29996224276349,29996224276409,

144

Гпава 5

29996224276423,29996224276519,29996224276523,29996224276549,

29996224276561,29996224276567,29996224276591,29996224276633,

29996224276727,29996224276771,29996224276861,29996224276883,

29996224276891,29996224276937,29996224276939,29996224276957,

29996224276987,29996224277027,29996224277077,29996224277113,

29996224277191,29996224277209,29996224277291,29996224277293,

29996224277317,29996224277329,29996224277413,29996224277441,

29996224277557,29996224277563,29996224277599,29996224277627,

29996224277651,29996224277653,29996224277693,29996224277699,

29996224277753,29996224277777,29996224277801,29996224277807,

29996224277839,29996224277977,29996224278001,29996224278029,

29996224278079,29996224278091,29996224278107,29996224278109,

29996224278113,29996224278121,29996224278131,29996224278133,

29996224278169,29996224278179,29996224278197,29996224278211,

29996224278283,29996224278409,29996224278443,29996224278457,

29996224278539,29996224278551,29996224278571,29996224278611,

29996224278653,29996224278689,29996224278847,29996224278857,

29996224278949,29996224278967,29996224279013,29996224279019,

29996224279031,29996224279037,29996224279039,29996224279081,

29996224279097,29996224279139,29996224279157,29996224279249,

29996224279303,29996224279309,29996224279367,29996224279379}

Здесь построена таблица простых чисел

, pIQl2+2,

/V +ioo* И уж, конечно,

не составляет труда вычисление отдельного простого числа рл по его номеру л..., если только л не слишком велико. Вот примеры.

Prime[2Л42]

138666449011757

п=2л42+2л32;Prime[п]

138806309513323

п=2л42+2л38;Prime[п]

147626019875161

Но если л очень велико, система Mathematica откажется вычислять Prime [п].

п=2Л43; Prime [п]

Prime::largp

Argument 8796093022208 in Prime[8796093022208]

is too large for this implementation. More...

Prime[8796093022208]

В таких случаях вам придется решать, что делать: строить решето или использовать другие методы. Говорят, впрочем, что верхнюю планку для аргумента п функции

Prime [п] скоро поднимут примерно до 260 Не слишком высоко, до бесконечности еще идти и идти, но даже того, что есть, более чем достаточно для классических учеб­ ников (и задачников) по теории чисел.

Поиск отрезков натурального ряда, состоящих только из составных чисел

За одним-единственным исключением рх = 2 , р2 = 3, числа рл и рп+1 не явля­

ются смежными в натуральном ряду. Еще Евклид знал, что существуют сколь угодно длинные отрезки натурального ряда, целиком состоящие из составных чисел. Как же найти отрезок натурального ряда, целиком состоящий из составных чисел? Для этого полезно определить следующую функцию.

Арифметика: простые числа

145

C o m p o siteR u n s[n_Integer?Positive]:=Block[{pl,p2=3,i=2},While[{pi,p2}=

{p2,Prime[++i]};p2-pl<n+l];Range[pl+l,pl+n]]

Вот как ее можно использовать.

CompositeRuns/@Range[10]

Здесь она запускается 10 раз. Вот что получится (вывод немного отформатирован).

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}}

Как видите, она находит отрезок натурального ряда заданной длины, целиком со­ стоящий из составных чисел. С ее помощью легко найти и отрезок длиной 150, цели­ ком состоящий из составных чисел.

CompositeRuns[150]

[4652354,4652355,4652356,4652357,4652358,4652359,4652360,4652361, 4652362,4652363,4652364,4652365,4652366,4652367,4652368,4652369,- 4652370,4652371,4652372,4652373,4652374,4652375,4652376,4652377, 4652378,4652379,4652380,4652381,4652382,4652383,4652384,4652385, 4 652386, 4652387, 4652388,4652389, 4652390, 4652391, 4652392,4 652393, 4652394,4652395,4652396,4652397,4652398,4652399,4652400,4652401, 4652402, 4652403, 4652404,4652405, 4652406,4 652407,4652408,4 652409, 4652410,4652411,4652412,4652413,4652414,4652415,4652416,4652417, 4652418,4652419,4652420,4652421,4652422,4652423,4652424,4652425, 4652426,4652427,4652428,4652429,4652430,4652431,4652432,4652433, 4652434,4652435,4652436,4652437,4652438,4652439,4652440,4652441, 4652442,4652443,4652444,4652445,4652446,4652447,4652448,4652449, 4652450,4 652451,4 652452, 4652453, 4652454, 4652455, 4652456, 4652457, 4652458,4652459,4652460,4652461,4652462,4652463,4652464,4652465, 4652466,4652467,4652468,4652469,4652470,4652471,4652472,4652473, 4652474,4652475,4652476,4652477,4652478,4652479,4652480,4652481, 4652482, 4652483,4 652484, 4652485,4 652486,4652487, 4652488, 4652489, 4652490,4652491,4652492,4652493,4652494,4652495,4652496,4652497, 4652498,4652499,4652500,4652501,4652502,4652503}

Однако полезнее эту функцию модифицировать так, чтобы она выводила на печать только длину отрезка и его начало.

CompositeRunsStart[n_Integer?Positive]:=Block[[pl,p2=3,i=2),

While[ [p i,p 2 ) = { p 2 ,P r im e [ + + i] } ; p 2 - p l< n + l]; P r i n t [ [n, p l + 1 ) ]]

Тогда вывод выглядел бы так (конец обрезан).

CompositeRunsStart/@Range[200]

[1,4]

<2,8)

[3,8]

{4,24}

[5,24]

[6,90]

{7,90]

{8,114}

146

Гпава 5

{9,114}

{10,114} {11,114 } {12,114} {13,114} {14,524}

Однако среди этой информации все еще слишком много шума. Логично было бы исключить избыточную информацию.

{1,4}

{3,8}

{5,24}

{7,90}

■{13,114}

Таблица стала, как видим, значительно компактнее и информативнее. Однако для построения такой таблицы ни функцией CompositeRuns, ни функцией CompositeRunsStart пользоваться не выгодно: обе функции начинают вычисления, не используя уже вычисленных значений, и потому при построении такой таблицы для каждого ее значения начинали бы вычисления с самого начала. Поэтому для по­ строения такой таблицы лучше воспользоваться специальной программой. Для начала подойдет, например, следующая программа.

n=l;pl=3;p2=3;i=2;n=l;nl=n;

While[n<=292, {Print[{n, pl+1}]; While[nl<=n,

{pl=p2,

p2=Prime[++i], nl=p2-pl-l}];

n=nl}]

Эта программа выводит список пар. В каждой паре сначала указана длина интер­ вала, а затем — его начало, причем указывается, естественно, начало того ближайшего к началу натурального ряда интервала, который имеет указанную длину. Длина же для данного начала указана наибольшая: она не может быть увеличена, так как следующее за указанным интервалом число — простое. Полученные результаты, весьма нетриви­ альные, удобно представить в виде таблицы (табл. Б.21).

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

LargestPrimeGap[n_Integer?(#<3&)]:=

Max[Drop[#,1]-Drop[#,-1]&[Prime/@Range[2,PrimePi[n]]]]

Данная функция определяет наибольшую разность между двумя последовательными простыми числами, не превосходящими п. Заметьте, что для определения количества простых чисел, не превосходящих л, здесь используется функция PrimePi [п], которая в теории чисел обозначается как тс(л:). Но имя функции PrimePi вполне оправдано, поскольку имя Pi зарезервировано для константы л. Функция LargestPrimeGap не является, конечно, обратной в строгом смысле ни к функции CompositeRuns, ни к функции CompositeRunsStart, ни к написанной нами программе. Однако она дела­ ет нечто, что помогает “обратить” полученную нами таблицу. Давайте определим, на­ пример, длину наибольшего интервала из составных чисел, не превосходящих 11. Сначала вычислим наибольшую разность между двумя последовательными простыми числами, не превосходящими 11.

Арифметика: простые числа

147

LargestPrimeGap[11]

4

Длина же интервала, естественно, на единицу меньше. И действительно, мы имели пару {3, 8}, что указывало, что первым числом в интервале длины 3 является 8. (Ну а 8+3 = И.) Давайте теперь применим функцию LargestPrimeGap к нахожде­ нию наибольших разностей между двумя последовательными простыми числами, не превосходящими степеней некоторых чисел. В качестве оснований возьмем 2, е, 3, 5, 7, 10. Сначала попробуем провести вычисления, скажем, до 28 степени.

Do[Print[{n,LargestPrimeGap[2An]}],{n,2,28}]

При выполнении этой программы получаются следующие результаты.

{3,2}

{4,4}

{5,6}

{6 , 6 }

{7,14}

{8,14}

{9,14}

{1 0 , 2 0 }

{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 еще слишком мало, чтобы длина интервала из­ менялась существенно. Однако при вычислении последних значений на слабом компьютере ощущается заметное падение быстродействия. С чем это связано? Давайте перейдем к более естественному основанию — основанию натуральных логарифмов — и проверим, закономерно ли это.

Вот нужная нам программа.

D o[Print[ {n, LargestPrimeGap[IntegerPart[EAn ] ]}], {ri, 2, 19}]

Вот что получилось.

{ 2 , 2 }

{3,4}

{4,6}

{5,14}

{6,14}

{7,20}

{8,34}

{9,34}

{10,52}

148

Гпава 5

{11,72}

{ 1 2 , 8 6 }

{13,112}

{14,114}

{15,148}

{16,154}

{17,210}

{18,220}

{19,222}

Действительно, это основание кажется наиболее естественным, хотя все же нельзя не отметить хаотичность увеличения разностей и на этот раз. Но что подтвердилось — так это существенное падение быстродействия. Чтобы выяснить, с чем это связано, давайте запустим Диспетчер задач Windows. Изменим несколько нашу программу.

base=3;Do[Print[{n, LargestPrimeGap[baseAn]}],{n,2,17}]

Вот полученные результаты.

{2 , 2 }

{3,4}

{4,6}

{5,14}

{6,18}

{7,34}

{8,34}

{9,52}

{10,72}

{11, 8 6 }

{12,114}

{13,132}

{14,154}

{15,154}

{16,210}

{17,222}

Когда быстродействие упало, я бы сказал, даже не до нуля, а до безобразия, я сде­ лал копию экрана Диспетчера задач Windows (рис. 5.1). Из нее хорошо видна причина снижения быстродействия — слишком большой файл подкачки и высокая интенсив­ ность страничного обмена. Из-за этого фактически система пробуксовывает, процент загрузки центрального процессора (ЦП) не повышается выше 30.

Теперь выполним наши вычисления для основания 5. На этот раз система Mathematica сама подскажет причину падения быстродействия.

base=5;Do[Print[{n, LargestPrimeGap[baseAn]}],{n,2,17}] {2,4} {3,8} 14,18} {5,34} {6,36} {7,72}

{8, 1 12}

19,132}

{10,154}

{11, 220}

{12,248}

No more memory available.

Mathematica kernel has shut down.

Try quitting other applications and then retry.

Арифметика: простые числа

149

Е Диспетчер задач Windows

ш

Файл Параметры Вид

Завершение работы Справка

j Приложения i! ГЬоцессы ]! Быстродействие jjceTb

Е Погьзователи]

Загрузка ЦП

Хронология загрузки ЦП

 

Файл подкалки

Хронология использования файла подкачки

Всего

 

Физическая память (КБ)

Деосрттсрое

7051

Всего

1047276

Потоков

373

Доступно

1800

Процессов

41

Систегиьйюш

9396

Выделение памяти (КБ)

Память ядра (КБ)

 

Всего

1413864

Всего

51044

Предел

2S20712

Вьгружееная

24724

Пик

2059240

Невыгружаемая

26320

Рис. 5.1. Вот как растет файл подкачки

Хотя мы и получили довольно интересные результаты, завершение вычислений было несколько неожиданным. Давайте попробуем с основанием 7.

base=7;Do[Print[{n, LargestPrimeGap[baseAn]}],{0,2,15}]

{ 2 , 6 }

{3,14}

{4,34}

{5,44}

{6,72}

{7,114}

{8,154'}

{9,210}

На сей раз предупреждение не появилось, но вычисления пришлось прервать. На экране Диспетчера задач Windows хорошо видно плато, где загрузка ЦП высока, и почти отвесное ее падение (рис. 5.2).

150

Гпава 5