23. Arytmetyka
Treści kształcenia. Arytmetyka liczb całkowitych: podzielność, NWD i NWW, algorytm Euklidesa i rozszerzony algorytm Euklidesa, liczby pierwsze i sito Eratostenesa. Kongruencje (arytmetyka modularna), odwrotność modulo , małe twierdzenie Fermata i liczby Carmichaela.
Efekty kształcenia. Potrafi wyznaczać NWD, NWW i odwrotności modulo (algorytm Euklidesa i jego rozszerzona wersja) oraz wykonywać obliczenia na kongruencjach. Potrafi stosować małe twierdzenie Fermata do wykazywania, że dana liczba jest złożona, i zna ograniczenia tego testu (liczby Carmichaela).
Liczby całkowite¶
Na tych zajęciach skupimy się na arytmetycznych własnościach liczb całkowitych. W szczególności interesować nas będzie podzielność, związki dodawania z mnożeniem i zastosowania w szczególnych działach informatyki takich jak kryptografia.
Liczby całkowite (jako zbiór) oznaczamy symbolem . Zbiór ten zawiera liczby naturalne (z zerem), których zbiór oznaczamy . Liczby całkowite, które nie są naturalne, nazywamy liczbami ujemnymi.
Na zbiorze liczb całkowitych określamy dwie operacje dodawania () i mnożenia (). Obie te operacje są naturalnym rozszerzeniem analogicznych operacji zdefiniowanych na zbiorze liczb naturalnych.
Wraz z operacjami liczby całkowite tworzą pierścień.
Podzielność¶
Mnożenie liczb całkowitych ma bardzo bogatą strukturę. Przy jego wykonywaniu ważną relacją pomiędzy liczbami całkowitymi jest podzielność.
Definicja
Liczba całkowita jest podzielna przez liczbę całkowitą , o ile istnieje liczba całkowita , które razem spełniają
Mówimy, że jest dzielnikiem liczby , gdy zachodzi powyższa relacja. Oznaczamy ją .
Proste wnioski:
Liczba 0 jest podzielna przez dowolną liczbę całkowitą.
Liczba 1 jest dzielnikiem dowolnej liczby całkowitej.
Dla każdej liczby całkowitej zachodzi .
Jeśli oraz , wówczas lub .
Jeśli i , to .
Największy wspólny dzielnik¶
Dla dwóch liczb całkowitych takich, że , największą dodatnią liczbę całkowitą, która dzieli oraz , nazywamy największym wspólnym dzielnikiem i oznaczamy .
Standardowo przyjmowaną konwencją jest .
Zauważmy, że oraz .
Twierdzenie (Euklides) Niech będą liczbami całkowitymi. Zachodzi równość
W szczególności oznacza to, że dla dowolnej liczby całkowitej zachodzi
Mając dane dwie liczby całkowite , takie, że , istnieje dokładnie jedna para liczb całkowitych spełniająca oraz
Liczbę nazywamy resztą z dzielenia liczby przez .
Algorytm Euklidesa¶
Powyższe twierdzenie udowodnione przez Euklidesa w księdze VII pozwala nam napisać bardzo prosty i szybki algorytm obliczenia największego wspólnego dzielnika.
Wejście: dwie liczby nieujemne Wyjście: największy wspólny dzielnik .
Algorytm:
Jeśli , zwróć i zakończ algorytm.
Niech będzie resztą z dzielenia przez .
Podstaw za liczbę .
Podstaw za liczbę .
Wróć do kroku 1.
def NWD(a,b):
a=abs(a) #liczby nieujemne
b=abs(b)
while b!=0: #dopóki b jest różne od 0, wykonuj pętlę
r = a%b #reszta z dzielenia a przez b
a = b
b = r
return aNWD(15,19)1Zadanie 1 (NWD)¶
Oblicz największy wspólny dzielnik liczb i 2100. Czy do tego celu musisz wyznaczyć wszystkie cyfry dziesiętne obu liczb?
Najmniejsza wspólna wielokrotność¶
Dla dwóch liczb całkowitych niezerowych najmniejszą dodatnią liczbę całkowitą, która jest podzielna przez oraz , nazywamy najmniejszą wspólną wielokrotnością i oznaczamy . Liczba taka zawsze istnieje, bo jest dodatnią liczbą podzielną przez oraz . Ponadto jest ona dzielnikiem . Zachodzi równość
Liczby całkowite, dla których , nazywamy względnie pierwszymi.
Liczby pierwsze¶
W zbiorze liczb całkowitych z relacją podzielności wyróżniamy pewien szczególny podzbiór liczb, które mają mało dzielników.
Definicja
Niech będzie liczbą całkowitą większą niż 1. Liczba jest liczbą pierwszą, gdy jedynymi jej dodatnimi dzielnikami są 1 oraz .
Twierdzenie
Niech będzie liczbą naturalną. Istnieje algorytm, który zwraca różnych liczb pierwszych.
Dowód
Dowód tego twierdzenia można zrealizować na bardzo wiele sposobów. Omówimy sobie jeden, który pochodzi (ponownie) od Euklidesa.
Zaczynamy od . Wówczas liczba 2 jest pierwsza i zwracamy zbiór .
Dla małych wartości możemy poszukiwać kolejnych liczb pierwszych, ale takie przeszukiwanie nie daje gwarancji, że znajdziemy liczb pierwszych dla każdego .
Zastosujemy następujący trik. Mając dany zbiór składający się z różnych liczb pierwszych, rozważamy liczbę
Liczba jest większa od 1 oraz jest względnie pierwsza z każdą z liczb . Oznacza to, że albo sama jest liczbą pierwszą, gdy ma dokładnie dwa dodatnie dzielniki, albo jest liczbą złożoną.
Gdy jest liczbą złożoną, wówczas musi mieć dwa nietrywialne dzielniki i postać , gdzie . Korzystając z zasady indukcji matematycznej możemy udowodnić, że taki rozkład prowadzi do znalezienia dzielnika pierwszego liczby . Dzielnik ten (skoro liczby oraz są względnie pierwsze) jest liczbą pierwszą różną od elementów .
Kładziemy , gdy jest pierwsza lub jest dowolnym (np. najmniejszym) pierwszym dzielnikiem liczby . Tworzymy zbiór
def najmdzielnik(n): #najmniejszy dodatni dzielnik liczby n (udowodnij, że zawsze jest liczbą pierwszą!)
for i in range(2,floor(sqrt(n))+1):
if n%i==0:
return i
else:
return n
def Euklides(N):
if N==1:
return [2]
else:
c=1
E=Euklides(N-1)
for el in E:
c*=el
p=najmdzielnik(c+1)
return E+[p]Euklides(15) #uwaga dla dużych argumentów algorytm działa bardzo wolno[2,
3,
7,
43,
13,
53,
5,
6221671,
38709183810571,
139,
2801,
11,
17,
5471,
52662739]Zadanie 2 (podzielność iloczynu przez liczbę pierwszą)¶
Uzasadnij, że gdy liczba pierwsza dzieli iloczyn , to dzieli lub dzieli .
Sito Eratostenesa¶
Efektywnym sposobem generowania kolejnych liczb pierwszych do zadanego górnego ograniczenia jest tzw. sito Eratostenesa. Jest to algorytm, który dla zadanej na wejściu liczby naturalnej zwraca listę wszystkich liczb pierwszych nie większych od .
Kroki algorytmu.
Wygeneruj ciąg długości składający się z dwóch zer i jedynek, elementy ciągu oznaczamy i indeksujemy je liczbami .
Ustawiamy pozycję startową .
Jeśli , wówczas zwracamy na wyjście element , który jest liczbą pierwszą.
We wszystkich pozycjach o indeksach postaci wstawiamy liczbę 0.
Zwiększamy wartość indeksu o 1.
O ile , wracamy do kroku 3. W przeciwnym przypadku kończymy algorytm.
def Sito(N):
lpierwsze=[]
a=[0,0]+[1]*(N)
t=2
while t < N:
if a[t]==1:
lpierwsze.append(t)
for k in range(2,ceil(N/t)):
a[t*k]=0
t+=1
return lpierwszeSito(40)[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]Zadanie 2* (wyzwanie)¶
Uzasadnij, że gdy , to .
Uzasadnij, że .
(*) Uzasadnij, że dla liczb Fibonacciego dla zawsze istnieje liczba pierwsza , która dzieli , ale nie dzieli dla żadnego .
Uwaga! Ostatnie zadanie jest twierdzeniem udowodnionym przez R. D. Carmichaela w 1913 roku. Praca zawierająca dowód jest dostępna tutaj.
Przeanalizuj poniższy kod algorytmu, który generuje najmniejsze nowe dzielniki pierwsze pojawiające się w ciągu Fibonacciego.
Uzasadnij, że dla każdej liczby pierwszej liczba lub jest podzielna przez . W celu lepszego zrozumienia tego zjawiska obejrzyj odcinek serii ,,Numberphile’’ na YouTube.
def FibPierw(N):
lp=[3]
for i in range(4,N):
f=fibonacci(i)
for p in lp:
while f%p==0:
f/=p
if f>1:
q=najmdzielnik(f)
lp.append(q)
return lp
FibPierw(30)[3,
5,
2,
13,
7,
17,
11,
89,
233,
29,
61,
47,
1597,
19,
37,
41,
421,
199,
28657,
23,
3001,
521,
53,
281,
514229]Arytmetyka modularna¶
Za pomocą relacji podzielności możemy wprowadzić na liczbach całkowitych relację kongruencji. Dwie liczby całkowite przystają do siebie modulo , gdy zachodzi podzielność
Wprowadzamy nową notację
Podstawowe własności kongruencji¶
Relacja jest relacją równoważności, tj. spełnia trzy warunki
.
implikuje .
i implikuje .
Zadanie 3 (własności kongruencji)¶
Uzasadnij korzystając z definicji relacji podzielności własności . Udowodnij ponadto
i implikuje
i implikuje
Rozszerzony algorytm Euklidesa¶
Dla dwóch niezerowych liczb całkowitych istnieją dwie inne liczby całkowite spełniające równanie
Algorytm Euklidesa, którym obliczaliśmy , można rozszerzyć tak, aby wyznaczał liczby . Jego podstawową ideą jest przekształcanie dwóch trywialnych równań
oraz
poprzez dodawanie ich stronami. Po prawej stronie równania wykonując kroki jak w klasycznym algorytmie Euklidesa otrzymamy finalnie liczby 0 i . Równanie, w którym prawą stroną jest , będzie odpowiadało współczynnikom spełniającym równość . Poniżej prezentujemy krótki kod z implementacją.
def xyNWD(a,b):
r,r1=a,b
s,s1=1,0 #s*a+t*b == a
t,t1=0,1 #s1*a+t1*b == b
while not(r1==0):
q,r2=r//r1,r % r1
r,s,t,r1,s1,t1=r1,s1,t1,r2,s-s1*q,t-t1*q
d=r
return d,s,t #s*a+t*b=d, d=GCD(a,b)xyNWD(199,231)(1, -65, 56)199*(-65)+231*561Zadanie 4¶
Uzasadnij, że dla dwóch kolejnych liczb Fibonacciego oraz algorytm xyNWD(a,b) zwróci liczby , oraz .
Wskazówka 1:
Udowodnij następującą tożsamość
dla dowolnego .
Wskazówka 2:
Tożsamość wynika z definicji macierzowej liczb Fibonacciego (+ własności wyznacznika macierzy 2x2).
Wskazówka 3:
Tożsamość można udowodnić korzystając z formuły Bineta.
f=lambda k: xyNWD(fibonacci(k),fibonacci(k+1))==(1,(-1)^k*fibonacci(k-1),(-1)^(k-1)*fibonacci(k-2))
[f(i) for i in range(2,10)][True, True, True, True, True, True, True, True]Rozszerzony algorytm Euklidesa pozwala nam znajdować odwrotności liczb modulo . Konkretnie - mając daną liczbę oraz względnie pierwszą dodatnią liczbę całkowitą , z rozszerzonego algorytmu Euklidesa wynika, że istnieją całkowite spełniające równanie
Oznacza to, że . Liczbę nazywamy multiplikatywną odwrotnością modulo .
Zadanie 5 (odwrotność multiplikatywna)¶
Znajdź odwrotności multiplikatywne dla liczby 2 modulo .
Prawo skracania¶
Jeśli mamy daną kongruencję i liczby oraz są względnie pierwsze, wówczas zachodzi kongruencja
Do udowodnienia tej własności wykorzystujemy własność 5. wraz z istnieniem odwrotności modulo dla liczby .
Małe twierdzenie Fermata¶
Dla dowolnej liczby całkowitej oraz liczby pierwszej zachodzi następująca równość
Dowód tego interesującego twierdzenia pomijamy.
Zadanie 6 (małe twierdzenie Fermata)¶
Uzasadnij, że gdy , wówczas .
Uzasadnij (przez kontrapozycję), że jeśli dla dwóch względnie pierwszych liczb nie zachodzi , to nie jest liczbą pierwszą.
Wykorzystaj , aby uzasadnić, że nie jest liczbą pierwszą (użyj 2).
Przy wykonywaniu potęgowania modulo najlepszy efekt uzyskamy wykonując redukcję liczby przy każdej operacji potęgowania. Ponadto stosujemy algorytm szybkiego potęgowania!
pow(2,1110,1111) #==(2**(1110))%1111 - uwaga proszę nie wyznaczać 2**1110 bez redukcji!1024Fermat spekulował, że liczby postaci są pierwsze dla wszystkich naturalnych. Sprawdź korzystając z testu Fermata przy podstawie 3, że oprócz czterech pierwszych wartości (które istotnie są pierwsze!) żadna z liczb Fermata dla nie jest liczbą pierwszą.
Czy potrafisz znaleźć wszystkie dzielniki pierwsze tych liczb?
f = lambda k: pow(3,2^(2^k),2^(2^k)+1)
[f(k) for k in range(1,12)]
[1,
1,
1,
1,
3029026160,
8752249535465629170,
47511664169441434718291075092691853899,
113080593127052224644745291961064595403241347689552251078258028018246279223993,
13387457852131866017809974335626508736765841341908171621341620739066502578793457441078230804865246011339933833061458906559278633032869468345609327807927612,
146809528970244036024821005514683473483244699825046485942988727983049278671435326268165085575181832374726912946280018892919388962699993405908818784177788470178225764936427450039582955979907044211973217849267621360435307454207055855850222255439616231847463892347771894224104545724927599853426578286430466818141,
30182254562411366016290758815250615385119773900166287071320012103534598658748016249356706212399576409176051623391493996034124229337964810272435823998759626339401861304936841613905227081361815373560623362517120490947404339480460474313332173820677516012404946143838387043195618836260126897873905424390972879492407142873302089766617045846445406669503126391560898750223711517657699612890637345675153011392343307620981019447351020682006327614009099495824926766595975575854120577153137811068800000938167385336783270712238367290842981503683862065572101540670645762238184533792146272643893152798145446980427283893716719008826]Uwaga!
Istnieją liczby naturalne złożone, które spełniają dla każdej liczby całkowitej . Takie liczby nazywamy liczbami Carmichaela.
Zadanie 7 (liczby Carmichaela)¶
Wyznacz pierwszych 5 liczb Carmichaela.
def najmdzielnik(n): #najmniejszy dodatni dzielnik liczby n (udowodnij, że zawsze jest liczbą pierwszą!)
for i in range(2,floor(sqrt(n))+1):
if n%i==0:
return i
else:
return n
def JestCarm(p):
for n in range(p):
if not(pow(n,p,p)==n):
return False
return True[k for k in range(5000) if JestCarm(k) and not(najmdzielnik(k)==k)] #sprawdzamy czy liczba k nie jest pierwsza i spełnia warunek Carmichaela[561, 1105, 1729, 2465, 2821]Dodatkowe zadania¶
Przeanalizuj poniższy algorytm
DzienTygodniawyznaczania dnia tygodnia w kalendarzu gregoriańskim. (0-niedziela, 1- poniedziałek, ...)Zapoznaj się z metodą walidacji kodu ISBN.
Zapoznaj się z testem pierwszości Millera-Rabina.
Na 15 stycznia 2023 największą znaną liczbą pierwszą jest liczba Mersenna . Przeczytaj o projekcie GIMPS, aby przekonać się, w jaki sposób weryfikuje się pierwszość tak dużych liczb.
Niech będzie liczbą pierwszą, dla której dzieli . Przekonaj się, że dla zachodzi taka własność. Poczytaj o hipotezie, że takich liczb pierwszych ma być nieskończenie wiele.
Rozważ następującą funkcję określoną na zbiorze liczb naturalnych dodatnich
Sprawdź dla wszystkich liczb naturalnych mniejszych od 100, że ciąg liczb zawsze trafia do jedynki.
Hipoteza Collatza
Udowodnij, że tak jest dla każdej liczby naturalnej.
def DzienTygodnia(year, month, day): #Sakamoto algorithm
t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
if month < 3:
year -= 1
return (year + year // 4 - year // 100 + year // 400 + t[month - 1] + day) % 7
year = 2022
month = 8
day = 31
print(gauss_day_of_week(year, month, day)) # Wyjscie: 3 (Sroda)3
- Carmichael, R. D. (1913). On the Numerical Factors of the Arithmetic Forms α n ± β n. The Annals of Mathematics, 15(1/4), 30. 10.2307/1967797