Kody i szyfry
2. Kody numeryczne i arytmetyka cyfrowa
2.15. Zapisy resztowe
Zapis resztowy to inaczej zapis rezidualny lub zapis RNS (od ang. Residue Number System). Koncepcja zapisu rezidualnego (lub nieco ogólniej arytmetyki ) pochodzi od A.Svobody i M.Valacha i została podana w pracy zamieszczonej w czeskim czasopiśmie ”Stroje na Zapracovani Informaci” w roku 1955. Niezależnie od A.Svobody i M.Valacha pomysł zapisu rezidualnego podał w 1959 r. H.L.Garner w pracy opublikowanej w IRE Transactions EC-8.
Zapis resztowy umożliwia realizację szybkiej arytmetyki (dokładniej: dodawania, odejmowania i mnożenia) bez propagacji przeniesień. Mnożenia które są dosyć złożonymi działaniami (a np. w cyfrowym przetwarzaniu sygnałów mnożeń wykonujemy bardzo dużo) można jak zobaczymy wykonywać bardzo szybko i prosto. Skomplikowane stają się natomiast w zapisie RNS algorytmy dzielenia i porównania liczb.
Symbolem ![[x]_m [x]_m](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/77f716356f82a8f2d94d9a27e852b00c.gif) lub x (mod m) będziemy w dalszym ciągu oznaczać resztę z dzielenia liczby x ∈ Z przez liczbę m ∈ N, m ≥ N, m ≥ 2. Potrzebne nam będzie ponadto pojęcie kongruencji. Niech m ∈ N, m ≥ 2, mówimy, że dwie liczby a, b ∈ Z przystają modulo m jeśli dają tę samą resztę z dzielenia przez m. Zapisujemy to pisząc a ≡ b (mod m). Zapis taki nazywamy kongruencją modulo m.
 lub x (mod m) będziemy w dalszym ciągu oznaczać resztę z dzielenia liczby x ∈ Z przez liczbę m ∈ N, m ≥ N, m ≥ 2. Potrzebne nam będzie ponadto pojęcie kongruencji. Niech m ∈ N, m ≥ 2, mówimy, że dwie liczby a, b ∈ Z przystają modulo m jeśli dają tę samą resztę z dzielenia przez m. Zapisujemy to pisząc a ≡ b (mod m). Zapis taki nazywamy kongruencją modulo m.
Podstawą zapisu resztowego jest następujące chińskie twierdzenie o resztach.
Niech liczby naturalne m1,m2,...mn większe od jedności będą parami względnie pierwsze (tzn. dla każdego i ≠ j mamy NWD(mi,mj) = 1 wówczas dla dowolnych n liczb całkowitych x1,x2,...xn ∈ Z układ kongruencji liniowych
x ≡ x1 (mod mi)
...
x ≡ xi (mod mn)
ma dokładnie jedno rozwiązanie x w zbiorze <a,a + M − 1>, gdzie a ∈ Z, M = m1⋅m1⋅...mn. Rozwiązanie to jest dane wzorem
gdzie ki dla i = 1,2,3,...n są liczbami całkowitymi spełniającymi warunek
ki ≡ i (mod mi) dla i = 1,2,3,...,n
(3)
ki ≡ 0 (mod mj) dla i ≠ j
Dowód: Możemy znaleźć n liczb c1c2,...cn takich, że ci ∈  oraz ci
oraz ci ![\otimes _{m_i} \left[ \frac{M}{m_i} \right]_{m_{i}} \otimes _{m_i} \left[ \frac{M}{m_i} \right]_{m_{i}}](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/ba60c33960f02bcbd5ecbbda71525870.gif) = 1 (lub równoważnie ci jest elementem odwrotnym do elementu
 = 1 (lub równoważnie ci jest elementem odwrotnym do elementu ![\left[ \frac{M}{m_i} \right]_{m_i} \left[ \frac{M}{m_i} \right]_{m_i}](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/d05206ccd55603c96b8e6a2d6a934ca0.gif) w pierścieniu
 w pierścieniu  czyli ci =
 czyli ci = ![\left[ \frac{M}{m_i} \right]^{-i}_{m_{i}} \left[ \frac{M}{m_i} \right]^{-i}_{m_{i}}](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/2cd847fcc65feddcd531bc204c20bc89.gif) ). Łatwo sprawdzić, że ki = ci
). Łatwo sprawdzić, że ki = ci  i = 1,2,3,...,n spełniają warunek (**). Wynika to z tego, że NWD(
 i = 1,2,3,...,n spełniają warunek (**). Wynika to z tego, że NWD(![m_i,\left[ \frac{M}{m_i} \right]_{m_i} m_i,\left[ \frac{M}{m_i} \right]_{m_i}](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/ef7b5d853b297ad7a93441f2722b39b5.gif) ) = 1.
) = 1.
Niech będzie dana liczba x ∈ Z i niech liczby naturalne m1,m2,...mn większe od jedności będą parami względnie pierwsze. Zapisem resztowym liczby x nazywamy ciąg skończony
W ten sposób definiujemy kod numeryczny  →
 →  . Zakres tak zdefiniowanego zapisu RNS jest oczywiście równy
. Zakres tak zdefiniowanego zapisu RNS jest oczywiście równy  .
.
Dodawanie, odejmowanie i mnożenie liczb w zapisie resztowym jest wykonywane po współrzędnych. Dokładniej, jeśli mamy 2 liczby zapisane w zapisie resztowym  =
 = ![([a]_{m_1},[a]_{m_2},[a]_{m_n})  ([a]_{m_1},[a]_{m_2},[a]_{m_n})](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/967971d0c49c54160daba82644292e51.gif) =
 =  i
 i ![b = ([b]_{m_1}, [b]_{m_2},..., [b]_{m_n} b = ([b]_{m_1}, [b]_{m_2},..., [b]_{m_n}](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/b0475435998d49be526fb0b0e4ffb406.gif) =
 =  to wówczas (jeśli wynik działania należy do zakresu zapisu) algorytmy dodawania, odejmowania i mnożenia dane są wzorami
 to wówczas (jeśli wynik działania należy do zakresu zapisu) algorytmy dodawania, odejmowania i mnożenia dane są wzorami
gdzie  ,
,  ,
,  są odpowiednio dodawaniem, odejmowaniem i mnożeniem modulo
 są odpowiednio dodawaniem, odejmowaniem i mnożeniem modulo  .
.
Przyjmijmy m1 = 3 m2 = 5 m3 = 7 i niech x = 3, y = 6. Stosując zapis resztowy mamy x = (0,3,3,0), y = (0,1,6).
Dodając liczby x = (0,3,3,0), y = (0,1,6) w zapisie resztowym według zaproponowanego wyżej algorytmu mamy
x + y = (0,3,3,0) + (0,1,6) = ( )= (0,4,2)
 )= (0,4,2) 
Zauważmy, że x + y = 9 i zapisując 9 w zapisie resztowym mamy (0,4,2) a więc z zaproponowanego algorytmu otrzymaliśmy wynik prawidłowy.
Odejmując liczby y = (0,1,6) i x = (0,3,3), w zapisie resztowym według zaproponowanego wyżej algorytmu mamy
 y − x = (0,1,6) − (0,3,3,0) = ( ) = (0,3,3)
) = (0,3,3)
Zauważmy, że y − x = 3 i zapisując 3 w zapisie resztowym mamy (0,3,3) a więc z zaproponowanego algorytmu otrzymaliśmy wynik prawidłowy.
Mnożąc liczby x = (0,3,3,0), y = (0,1,6) w zapisie resztowym według zaproponowanego wyżej algorytmu mamy
 y ⋅ x = (0,1,6) ⋅ (0,3,3,0) = ( ) = (0,3,4)
) = (0,3,4)
Zauważmy, że y ⋅ x = 18 i zapisując 18 w zapisie resztowym mamy (0,3,4) a więc z zaproponowanego algorytmu otrzymaliśmy wynik prawidłowy.
Konwersja zapis NKB liczby x → na zapis RNS liczby x sprowadza się do obliczenia n reszt z dzielenia liczby x przez moduły m1, m2, m3, ..., mn.
Konwersja zapis RNS → zapis NKB jest nieco bardziej złożona. Podamy dwa algorytmy konwersji.
Podstawowy algorytm konwersji jest na ogół formułowany w samym chińskim twierdzeniu o resztach. Przypomnijmy algorytm:
Niech a1, a2, ..., an będzie zapisem RNS liczby x oraz M = m1, m2, ..., mn.
I. Znajdujemy liczby bj ∈ Z takie, że:
bj ⋅  = 1 (mod
 = 1 (mod  ) dla j = 1,2,...n).
) dla j = 1,2,...n). (8)
(8)
II. Jeśli x ∈ [0, M], to
x = [a1 ⋅b1 ⋅  + a2 ⋅b2 ⋅
 + a2 ⋅b2 ⋅  + ... +  an ⋅bn
 + ... +  an ⋅bn ]M,
]M, (9)
(9)
a ogólnie, jeśli x ∈ [a, a + m), to
x = a + (a1 ⋅b1 ⋅  + a2 ⋅b2 ⋅
 + a2 ⋅b2 ⋅  + ... +  an ⋅bn − a)(mod M).
 + ... +  an ⋅bn − a)(mod M). (10)
(10)
Konwersja wykorzystująca „mixed radix representation” (algorytm Garnera).
I. Niech (a1, a2, a3) będzie zapisem RNS liczby x. Definiujemy   stałych cij (liczymy je tylko jeden raz – wstępnie).
 stałych cij (liczymy je tylko jeden raz – wstępnie).
cij ⋅ mi ≡ 1 (mod mj) dla  1 ≤ i < j ≤ n, (11)
(11)
lub co na jedno wychodzi, poszukujemy odwrotności elementu ![[m_i]_{m_j} [m_i]_{m_j}](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/eb6bb4688594226828a6651e1871bd1c.gif) w pierścieniu
 w pierścieniu  , czyli takiego cij, że cij
, czyli takiego cij, że cij  mj = 1 w pierścieniu
 mj = 1 w pierścieniu  .
.
II. Obliczamy ciąg v1, v2,...vn gdzie v1 ∈ [0, mi, −1) będący zapisem mixed radix szukanej liczby x,
v1 := a1 (mod m1)
v2 := (a1 − v1)c12(mod m2)
v3 := ((a1 − v1)c13−v1)c23(mod m3) (12)
(12)
.
.
.
vr := ((un − v1)c1r − v2)c2n − ...− vr−1)cr−1,n (mod mn)
III. Obliczamy
x = vn ⋅mn−1 ⋅ ...⋅ m1  + vn−1 ⋅mn−2⋅ ...⋅m1  +...+ v3 ⋅m2 ⋅m1 + v2 ⋅m1 ⋅v1  (13)
(13)
Łatwo zauważyć, że w zapisie RNS złożoność konwersji z RNS → zapis binarny; zapis binarny RNS w pewnym stopniu zależy od wyboru modułów m1,m2,m3,...mn.
Dla modułów postaci 2e − 1 konwersja liczby x na jej zapis RNS jest bardzo prosta.
Ogólnie rzecz biorąc, jeśli mamy liczbę x ∈ Z otrzymujemy jej reprezentację resztową przez dzielenie x przez kolejne moduły mi, co daje ciąg (a1,a2,...ar). Jednak dla modułów postaci 2ei − 1, można zrobić tak:
x = atAt + at−1At−1 +...+ a1A + a0 (14)
(14)
gdzie A = 2ei i 0 ≤ ak < 2ej i dla każdego k = 0,1,...t.
Zatem:
u = a1 + at −1 + ... + a1 + a0 (mod 2ej − 1) (15)
(15)
ponieważ A ≡ (mod 2ej − 1) i ostatecznie:
ui = at + at −1 + ... + a0 (mod (2ej − 1)) (17)
(17)
Zajmijmy się modułami postaci mj = 2ej − 1, gdzie ej ∈ N, ej ≥ 2, dokładniej. Pokażemy jakie korzyści wynikają z wyboru modułów m1,m2,...mr tak, by było mj = 2ej − 1, ej ∈ N, ej ≥ 2. Zależy nam na tym, żeby były to moduły parami względnie pierwsze. Następujące twierdzenie stanowi kryterium na to, by dwie liczby postaci 2 − 1 i 2e − 1 były względnie pierwsze.
− 1 i 2e − 1 były względnie pierwsze.
Dowód: 1. Zauważmy, że zachodzi równość:
((2e − 1)(mod 2 − 1)) = 2e, (mod
− 1)) = 2e, (mod  ) − 1
) − 1 (18)
(18)
Jeśli e ≤  , to jest to oczywiste. Niech e>
, to jest to oczywiste. Niech e> . Równość (18) jest równoważna do kongruencji
. Równość (18) jest równoważna do kongruencji
(2e − 1) ≡ 2e (mod  ) − 1 (mod (2
) − 1 (mod (2 − 1))
− 1)) (19)
(19)
i dalej
2e(mod  ) 2
) 2 ...q
...q ≡ 2e mod
 ≡ 2e mod  (mod (2
 (mod (2 − 1))
− 1)) (21)
(21)
ale: 2 ≡ 1 (mod (2
 ≡ 1 (mod (2 − 1)) zatem prawdziwa jest równość (18).
− 1)) zatem prawdziwa jest równość (18).
2. Wracamy do dowodzonej równości. Niech e> (dla e=
 (dla e= równość jest oczywista) wówczas na mocy (18) i algorytmu Euklidesa NWD(2e − 1,2
 równość jest oczywista) wówczas na mocy (18) i algorytmu Euklidesa NWD(2e − 1,2 − 1) = NWD(2
− 1) = NWD(2 − 1,2e mod
− 1,2e mod  − 1).
 − 1).
Kolejno stosujemy wzór (18), czyli obliczamy resztę z dzielenia przez liczbę mniejszą, zauważmy przy tym, że NWD(e,  ) = NWD(
) = NWD( ,e (mod
,e (mod  )).
)).
Postępując zgodnie z algorytmem Euklidesa otrzymamy wreszcie, w kolejnym kroku, iloraz reszt =0.
Będziemy więc mieli: NWD(2e − 1,2 − 1) = NWD(2a− 1,20 − 1) = 2a − 1
− 1) = NWD(2a− 1,20 − 1) = 2a − 1
Wniosek: Liczby 2e − 1 i 2 − 1 są względnie pierwsze wtedy i tylko wtedy, gdy e i
 − 1 są względnie pierwsze wtedy i tylko wtedy, gdy e i  są względnie pierwsze.
 są względnie pierwsze.
Słowo maszynowe k-bitowe, ogólnie rzecz biorąc może być jednak takie, że 2k > mi lub 2k < mi . Jeśli moduły dają się zapisać w kodzie NKB na słowie maszynowym to jest to oczywiście wygodne, ale nie jest to niezbędne.
Zasadnicze znaczenie dla szybkości wykonywania działań arytmetycznych w zapisie resztowym mają sposoby wykonywania działań modulo m. Działania modulo m powinny być realizowane za pomocą odpowiednio zaprojektowanych układów.
Uogólnieniem zapisu RNS na liczby zespolone jest zapis resztowy QRNS (Quadratic Residue Numer System)
(Z / m1m2...mnZ) ≅ (Z / m1Z) ⊕ (Z / m2Z) ⊕ ...⊕ (Z / mnZ)
i izomorfizm zadany jest wzorem γ(x) = ([x] ,[x]
,[x] ,...,[x]
,...,[x] ). Jest to nieco inne sformułowanie chińskiego twierdzenia o resztach.
). Jest to nieco inne sformułowanie chińskiego twierdzenia o resztach.
![x = a + \left[ \displaystyle\sum^n_{i=1}k_ix_i \right]_M\qquad x = a + \left[ \displaystyle\sum^n_{i=1}k_ix_i \right]_M\qquad](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/da19183a8224dd6a4fa71d4940186234.gif)

![([x]_{m_1},[x]_{m_2},...x]_{m_n})\qquad ([x]_{m_1},[x]_{m_2},...x]_{m_n})\qquad](https://esezam.okno.pw.edu.pl/filter/tex/pix.php/faf793c437f6861892137132f8102702.gif)



