Windows — приложение по теории чисел на языке программирования C++
В работе на языке C++ написано вычислительное приложение, позволяющее легко решать задачи из значительной части университетского курса теории чисел: таблица простых чисел, структура и длина периода обыкновенной дроби, первообразные корни и индексы по большим модулям, системы индексов, значения мультипликативных функций и др.
Теория чисел — очень важный раздел математики. Разделы теории чисел лежат в основе таких областей, как криптография, компьютерная графика, кодирование информации и многие другие. Но при решении задач из теории чисел порой требуется большое количество времени.
Цель работы: автоматизирование решения задач из теории чисел и создание приложения, которое помогает при решении таких задач.
Задачи работы:
- Познакомиться с указанными разделами теории чисел
- Составить алгоритм работы приложения.
- Написать программный код.
- Выполнить тестирование программы и устранить недочёты.
Итак, сначала стоит рассказать о теории, которая использовалась в моём приложении.
Определение 1. [1] Показателем целого числа a по модулю m называется наименьшее положительное целое число n ((a, m) = 1), такое, что
an ≡ 1 ( mod m ).
Проще говоря, это наименьшая натуральная степень n, в которую нужно возвести число a, чтобы при делении an на m получался остаток, равный 1.
Показатель определен только для чисел a, взаимно простых с модулем m. При этом, если показатель числа a по модулю m определен, то он является делителем значения функции Эйлера φ(m)[1].
Чтобы показать зависимость показателя n от a и m, его также обозначают δm(a), а если m фиксировано, то просто δ(a).
Показатель числа по модулю в частности использовался для нахождения длины периода обыкновенной дроби.
Теорема 1. [1] Длина периода в разложении числа
в десятичную дробь равна δm(10) (данная теорема работает только для дробей со знаменателями, не кратными 2 и 5).
Доказательство[1].
Рассмотрим дробь 
Пусть δb(10) = k.
Согласно теореме о делении с остатком, 10a = bc0 + r1, где 0 ≤ r1 < b, (r1, b) = (10a, b) = 1, так что, в частности, r1 не может равняться 0, то есть 1 ≤ r1 < b. Для пары r1, b мы имеем те же условия что и для a, b, так что мы получаем неограниченную последовательность равенств:
10a = bc0 + r1
10r1 = bc1 + r2
…………
10rk-1 = bck-1 + rk (1)
где при всех i величины ri и ci таковы, что
1 ≤ ri < b, 0 ≤ ci =
< 10 (r0 = a) (2)
и при всех i имеем (ri, b) = 1.
Деля все члены равенств выше соответственно на 10b, 102b, …, 10kb, …, получаем
=
+
=
+
+
= … =
+
+ … +
+
= … (3)
Из этого находим
a ∙ 10k = (c0 ∙ 10k – 1 + c1 ∙ 10k – 2 + … + ck – 1) ∙ b + rk,
так что rk ≡ a ∙ 10k ≡ a (mod b), и поскольку 1 ≤ rk < b, 1 ≤ a < b, то rk = a.
Совпадение величин rk и a показывает, что после k шагов в последовательности равенств выше (1) они начинают периодически повторяться, т. е. ck + s = cs при всех s равных 0, 1, 2, …
Поскольку
→ 0 при увеличении n из равенств (3) получаем периодическое разложение
=
+
+ … +
+
+
+ … +
+ …
Или же сокращённо
= 0, (c0 c1 … ck – 1).
Можно утверждать, что найденный период дроби — наименьший.
Действительно, если
= 0, (c0 c1 … ck – 1),
то a ∙ 10l = (с0 ∙ 10l – 1 + … + сl – 1) ∙ b + a ≡ a (mod b), и поскольку (a, b) = 1,
то 10l ≡ 1 (mod b), так что наименьшее значение l = δm(10) = k. Теорема доказана.
Для примера определим длину периода дроби
.
Как уже ранее говорилось, определения длины периода дроби
необходимо вычислить значение δ7(10).
φ(7) = 6, значит d | 6 = 1; 2; 3; 6
Начинаем перебор:
101 ≡ 3 ( mod 7 )
102 ≡ 2 ( mod 7 )
103 ≡ -1 ( mod 7 )
106 ≡ 1 ( mod 7 ) - сравнимо с 1 по модулю 7
Значит, δ7(10) = 6 ==> длина периода дроби со знаменателем 7 равна 6
Действительно,
= 0,1428571428571… = 0,(142857).
В общем случае, когда знаменатель делится на 2 или 5, ситуация следующая:
Пусть r =
; (m, n) = (m, 2) = (m, 5) = 1
Пусть 10max{α, β} = 10γ
Тогда r ∙ 10γ =
= 2γ- α ∙ 5γ- β ∙ 
Значит, r =
∙ 
Так как числитель не влияет на длину периода дроби, то длина периода дроби с указанным знаменателем равна δm(10), а период будет смещён на γ знаков вправо. В таком случае разложение дроби будет смешанным. [1]
Определение 2. [2] Число a ( (a, m) = 1) называют первообразным корнем по модулю m ( ПК (m) ), если δm(a) = φ(m) (φ(m) — функция Эйлера, количество чисел взаимно простых с m и не превосходящих его).
Теорема 2. [1] Первообразные корни существуют только по модулям 2, 4, p, pα, 2pα (p > 2).
Пусть g – ПК по модулю m. Тогда для любого целого a ( (a, g) = 1 ) существует такое число γ, что gγ ≡ a ( mod m ). Тогда число γ называют индексом числа по модулю m (при основании g). [2]
γ = indga
Индекс числа по модулю обладает логарифмическими свойствами, например:
- indg(a ∙ b) ≡ indg(a) + indg(b) ( mod φ(m) )
- indg(ab
) ≡ indg(a) - indg(b) ( mod φ(m) ) - indg(ak) ≡ k ∙ indg(a) ( mod φ(m) )
Ввиду практической пользы индексов составляются таблицы индексов по определённым К примеру, построим таблицу индексов по модулю 5. В качестве основания возьмём наименьший первообразный корень по модулю 5, то есть 2.
Так как 2 – ПК (5), то 2φ(5) = 24 ≡ 1 ( mod 5 )
Сначала определим индексы для чисел.
20 ≡ 1(5)
21 ≡ 2(5)
22 ≡ 4(5)
23 ≡ 3(5)
Построим таблицу индексов по данному модулю.
Удобнее построить 2 таблицы: для определения индекса по числу и числа по индексу.
m = 5; φ(m) = 4; g = 2
|
N |
1 |
2 |
3 |
4 |
|
0 |
0 |
1 |
3 |
2 |
|
I |
0 |
1 |
2 |
3 |
|
0 |
1 |
2 |
4 |
3 |
По модулю вида 2α таблица индексов строится так:
Если a ≡ (-1)γ ∙ 5γ₀ ( mod 2α ), то система γ, γ0 называется системой индексов числа a по модулю m (a = 2α). Причём,
c = 1, c0 = 1, если α = 0 или α = 1
c = 2, c0 = 2α – 2, если α ≥ 2 [2]
К примеру, построим таблицу систем индексов по модулю 8.
Так как 8 = 23, то c = 2, c0 = 2.
Построим все возможные сравнения для -1 и 5.
γ = 0 или 1, γ0 = 0 или 1.
(-1)0 ≡ 1 ( mod 8 )
(-1)1 ≡ -1 ( mod 8 )
50 ≡ 1 ( mod 8 )
51 ≡ -3 ( mod 8 )
Попарно перемножим сравнения для (-1) и 5.
(-1)0 ∙ 50 ≡ 1 ( mod 8 )
(-1)0 ∙ 51 ≡ 5 ( mod 8 )
(-1)1 ∙ 50 ≡ 7 ( mod 8 )
(-1)1 ∙ 51 ≡ 3 ( mod 8 )
И построим таблицу индексов по модулю 8 по полученным данным.
|
N |
1 |
3 |
5 |
7 |
|
γ |
0 |
1 |
0 |
1 |
|
γ0 |
0 |
1 |
1 |
0 |
Для произвольного составного модуля систему индексов строят следующим образом:
Пусть m = 2α ∙ p1α₁ ∙ p2α₂ ∙ … ∙ pkαₖ – каноническое разложение числа m. Пусть gs – наименьший первообразный корень по модулю psαₛ, s=1, .., k. Если
a ≡ (-1)γ ∙ 5γ₀ ( mod 2α )
a ≡ g1γ₁ ( mod p1α₁ ), … , a ≡ gkγₖ ( mod p1α₁ )
то система γ, γ0, γ1, … , γk называется системой индексов числа a по модулю m (всегда (a, m) = 1). [2]
Пример: Построим таблицу систем индексов по модулю 40.
40 = 23 ∙ 5, следовательно необходимо построить таблицы индексов по модулям 23 и 5.
Таблицы индексов по модулю 8 и 5 (были построены выше) можно легко продлить до модуля 40, исходя из следующих таблиц:
|
N |
1 |
3 |
5 |
7 |
9 |
11 |
13 |
15 |
17 |
... |
|
γ |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
... |
|
γ0 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
0 |
... |
|
N |
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
11 |
... |
|
γ1 |
0 |
1 |
3 |
2 |
0 |
1 |
3 |
2 |
0 |
... |
Из всех таблиц выберем столбцы с общим N и объединим их, тем самым составив таблицу систем индексов по модулю 40.
|
N |
1 |
3 |
7 |
9 |
11 |
13 |
17 |
19 |
|
γ |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
1 |
|
γ0 |
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
|
γ1 |
0 |
3 |
1 |
2 |
0 |
3 |
1 |
2 |
|
N |
21 |
23 |
27 |
29 |
31 |
33 |
37 |
39 |
|
γ |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
1 |
|
γ0 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
|
γ1 |
0 |
3 |
1 |
2 |
0 |
3 |
1 |
2 |
Заметим, что в таблицах индексов по любому m, все N взаимно просты с m.
Перейдём к самому приложению по теории чисел.
Реализуя поставленную цель, было решено написать приложение, с помощью которого можно переводить обыкновенную дробь в десятичную периодическую, находить длину периода дроби, показатель числа по модулю, значения различных мультипликативных функций, выводить таблицу простых чисел, делители числа, каноническое разложение числа, и с помощью которого можно составлять таблицы индексов по любому числу, не меньшему 2.
Для написания приложения был использован язык программирования C++ из-за быстроты выполнения кода. В моём случае скорость вычислений очень важна. Написание кода происходило в среде разработки Visual Studio. В Visual Studio очень удобно писать код и настраивать проект.
Сначала, уже поставив цель, была начата разработка функций, необходимых для реализации основной цели. Затем, мною разработано всё приложение.
В приложении есть основной класс MNT, внутри которого находятся все необходимые функции, а именно: таблицы простых чисел, делители числа, каноническое разложение числа, вычисления значений различных мультипликативных функций, показатель числа по модулю, деление столбиком, определение длины периода дроби, разложение обыкновенной дроби в десятичную периодическую, нахождение первообразных корней, построение таблиц индексов и систем индексов. Так же есть основная функция main, в которой прописано взаимодействие с пользователем.
Стоит сказать, что построение таблиц индексов и систем индексов работает по тому же алгоритму, приведённому в теоретическом блоке. Перевод обыкновенной дроби в десятичную периодическую работает же по следующему алгоритму:
1. Из знаменателя дроби m убираются множители 2α и 5β.
2. Вычисляется длина периода дроби по формуле δm(10).
3. Вычисляется γ = max{α, β}.
4. С помощью деления столбиком вычисляется ( γ + δm(10) ) знаков после запятой.
5. Перед знаком под номером γ + 1 ставим «(»
6. В конце ставим «)»
7. Выводим дробь.
При входе в приложение мы видим краткую справку по работе с ним, а именно какому действию соответствует какой номер.
Исходный код приложения расположен в открытом доступе в git репозитории.
Для работы с программой вам необходимо выбрать действие, а затем ввести необходимые данные. После ввода данных действие выполнится автоматически.
Пример 1: переведём дробь в десятичную периодическую с помощью моей программы. Сначала, выберем номер действия — 12, а затем введём по очереди числитель и знаменатель. Далее сразу выведется разложение данной дроби в десятичную периодическую.

Рисунок 1. Перевод обыкновенной дроби в десятичную периодическую с помощью приложения, интерфейс программы
Пример 2: составим таблицу индексов по модулю 97 с помощью данного приложения. Выберем номер действия — 15. Далее введём значение m и таблица сразу будет построена.

Рисунок 2. Построение таблицы индексов, часть 1

Рисунок 3. Построение таблицы индексов, часть 2
Пример 2: составим таблицу индексов по модулю 24 с помощью данного приложения. Выберем номер действия — 15. Далее так же введём значение m и таблица будет построена.

Рисунок 4. Составление таблицы индексов по составному модулю
Чтобы скачать данное приложение, вы можете воспользоваться следующими QR-кодами:

Рис. 5. QR-код версии приложения для Windows
Рис. 6. Исходный код приложения в qit-репозитории
В работе было написано приложение, содержащее значительную часть университетского курса теории чисел. С помощью него можно исследовать различные вопросы теории чисел: структура периода дроби, индексы по большим модулям, значения мультипликативных функций и ещё много интересного.
Цель работы была достигнута — было написано рабочее многофункциональное приложение для работы с разными областями теории чисел. Также были выполнены все поставленные задачи.
В данной работе предусмотрено дальнейшее улучшение приложения путем добавления новых функций.
- А. А. Бухштаб. Теория чисел — М.: Просвещенние, 1966, 384 с.
- И. М. Виноградов. Основы теории чисел — Москва-Ижевск: НИЦ Регулярная и хаотическая динамика, 2003, 176 с.
- М. Доусон. Изучаем C++ через программирование игр — СПб.: Питер, 2019, 352 с.



