INE5403 F UNDAMENTOS DE M ATEMÁTICA D ISCRETA PARA A C OMPUTAÇÃO P ROF. M AURO R OISENBERG UFSC - CTC - INE Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 1/2 2 - N ÚMEROS I NTEIROS 2.1) Divisão nos Inteiros 2.2) Números Primos e MDCs 2.3) Inteiros e Algoritmos 2.4) Aplicações de Teoria dos Números Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 2/2 I NTRODUÇÃO Existem várias classes de problemas que aparecem na Matemática Discreta: dada uma seqüência de inteiros, ache o maior; dado um conjunto liste todos os seus subconjuntos; dado um conjunto de inteiros, coloque-os em ordem crescente; dada uma rede de comunicação, ache o menor caminho entre dois vértices. Quando apresentado a estes problemas, a primeira coisa a fazer é construir um modelo que traduza o problema em um contexto matemático. Achar o modelo matemático adequado é apenas parte da solução. Para completar a solução é necessário um método que solucionará o problema geral utilizando o modelo. Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 3/2 I NTRODUÇÃO O método consiste em procedimento com uma seqüência de passos que levam até a resposta desejada. Tal seqüência de passos é chamada de um algoritmo. Definição: Um algoritmo é um conjunto finito de instruções precisas para realizar um cálculo ou solucionar um problema. O termo algoritmo muitas vezes é utilizado para designar procedimentos para realizar operações aritméticas usando a representação decimal dos inteiros. Estes algoritmos, adaptados para serem utilizados com a representação binária, são a base para a aritmética computacional. Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 4/2 R EPRESENTAÇÃO DOS I NTEIROS No nosso dia-a-dia utilizamos na notação decimal para expressar números inteiros. Por exemplo, 965 é utilizado para denotar 9.102 + 6.10 + 5. Podemos utilizar outras bases, além da decimal. Computadores normalmente utilizam notação binária (base 2) para realizar operações aritméticas. De fato, podemos utilizar qualquer inteiro positivo maior que 1 como base quando expressamos inteiros, como mostrado pelo seguinte teorema: Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 5/2 E XPANSÃO DE n NA BASE b Teorema 1: Seja b um inteiro positivo maior que 1. Então se n é um inteiro positivo, ele pode ser expresso de maneira única na forma n = ak bk + ak−1 bk−1 + · · · + a1 b1 + a0 onde k é um inteiro não negativo, a0 , a1 , · · · , ak são inteiros não negativos menores que b, e ak 6= 0. A expansão de n na base b (nome do Teorema 1) é denotada por (ak ak−1 · · · a1 a0 )b . Por exemplo, (245)8 representa 2.82 + 4.8 + 5 = 165. Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 6/2 E XPANSÕES B INÁRIAS Na notação binária, cada dígito pode ser 0 ou 1. Em outras palavras, a expansão binária de um inteiro é uma “cadeia” (string) de bits. Expansões binárias são utilizadas por computadores para representar e realizar a aritmética com inteiros. Exemplo 1: Qual a expansão decimal de um inteiro que possui (101011111)2 como sua expansão binária? (101011111)2 = 1.28 + 0.27 + 1.26 + 0.25 + 1.24 + 1.23 + 1.22 + 1.21 + 1.20 = 351 Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 7/2 E XPANSÕES H EXADECIMAIS 16 dígitos diferentes são necessários para esta expansão. Os dígitos hexadecimais utilizados são: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E e F , onde as letras A até F representam os dígitos correspondentes aos números 10 a 15 (na notação decimal). Exemplo 2: Qual a expansão decimal de um inteiro que possui (2AE0B)16 como sua expansão hexadecimal? (2AE0B)16 = 2.164 + 10.163 + 14.162 + 0.161 + 11.160 = (175627)10 Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 8/2 C ONVERSÃO DE BASE Como construir a expansão de um inteiro n na base b. Primeiro, divida n por b para obter um quociente e um resto, ou seja: n = bq0 + a0 , com 0 ≤ a0 < b. O resto, a0 , é o dígito mais a direita na expansão de n na base b. A seguir divida q0 por b para obter: q0 = bq1 + a1 , com 0 ≤ a1 < b. a1 é o segundo dígito da direita na expansão de n na base b. Continue este processo, dividindo sucessivamente os quocientes por b. Este processo termina quando se obtém um quociente igual a zero. Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 9/2 C ONVERSÃO DE BASE Exemplo 3: Ache a expansão octal (base 8) de (12345)10 . Primeiro, divida 12345 por 8 para obter 12345 = 8.1543 + 1 Sucessivamente divida os quocientes por 8 1543 = 8.192 + 7 192 = 8.24 + 0 24 = 8.3 + 0 3 = 8.0 + 3 Assim a expansão de 12345 na base 8 é dada pelos restos obtidos: (12345)10 = (30071)8 . Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 10/2 A LGORITMO PARA C ONVERSÃO DE BASE O pseudo-código a seguir acha a expansão (ak−1 · · · a1 a0 )b de um inteiro n na base b. Algoritmo 1: Construindo Expansões Base b procedure base b expansion(n:positive integer) q := n k := 0 while q 6= 0 begin ak := q mod b q := bq/bc k := k + 1 end {the base b expansion of n is (ak−1 · · · a1 a0 )b } Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 11/2 A LGORITMOS PARA O PERAÇÕES COM I NTEIROS Os algoritmos para realizar operações com inteiros usando suas representações em expansões binárias são extremamente importantes em aritmética computacional. Descreveremos algoritmos para adição e multiplicação de dois inteiros expressos como expansões binárias. Analisaremos a complexidade computacional destes algoritmos em termos do número de operações de bits necessárias para sua execução. Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 12/2 A LGORITMO PARA S OMA DE I NTEIROS Sejam dois números a e b cujas expansões binárias são: a = (an−1 an−2 · · · a1 a0 )2 , b = (bn−1 bn−2 · · · b1 b0 )2 , de tal forma que a e b possuem n bits (bits 0 podem ser colocados no início de uma das expansões se necessário). Para somar a e b, primeiramente some seus dígitos mais a direita: a0 + b0 = c0 .2 + s0 , onde s0 é o bit mais a direita na expansão binária de a + b e c0 é o "vai um" (carry ), que pode ser 0 ou 1. A seguir some o próximo par de bits e o carry, a1 + b1 + c0 = c1 .2 + s1 , onde s1 é o próximo bit na expansão binária de a + b, e c1 é o carry. Continue este processo, somando os bits correspondentes nas duas expansões binárias e o carry. Este processo produz a expansão binária da soma de a + b = (sn sn−1 sn−2 · · · s1 s0 )2 . Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 13/2 A LGORITMO PARA S OMA DE I NTEIROS Exemplo 4: Some a = (1110)2 e b = (1011)2 . a0 + b0 = 0 + 1 = 0.2 + 1. De forma que c0 = 0 e s0 = 1. Continuando o algoritmo: a1 + b1 + c0 = 1 + 1 + 0 = 1.2 + 0. De forma que c1 = 1 e s1 = 0. Continuando o algoritmo: a2 + b2 + c1 = 1 + 0 + 1 = 1.2 + 0. De forma que c2 = 1 e s2 = 0. Continuando o algoritmo: a3 + b3 + c2 = 1 + 1 + 1 = 1.2 + 1. De forma que c3 = 1 e s3 = 1. O que significa que s4 = c3 = 1. Assim, s = a + b = (11001)2 . Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 14/2 A LGORITMO PARA S OMA DE I NTEIROS O pseudo-código a seguir acha a expansão binária (sn sn−1 · · · s1 s0 )2 da soma da expansão binária de dois inteiros a e b. Algoritmo 2: Soma de Inteiros procedure add(a,b:positive integer) {the binary expansions of a and b are (an−1 an−2 · · · a1 a0 )2 and (bn−1 bn−2 · · · b1 b0 )2 respectively c := 0 for j = 0 to n − 1 begin d := b(aj + bj + c)/2c sj := aj + bj + c − 2d c := d end sn := c {the binary expansion of the sum is (sn sn−1 · · · s0 )2 } Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 15/2 A NÁLISE DO A LGORITMO Quantas adições de bits são necessárias no Algoritmo 2 para somar dois inteiros com n bits (ou menos) na sua representação binária? Dois inteiros são somados através da adição sucessiva de pares de bits, e de um carry, quando ele ocorre. Assim, o número total de adições de bits realizadas é menor ou no máximo igual a três vezes o número de bits da expressão. Podemos então dizer que o número de adições de bits realizadas pelo Algoritmo 2 para somar dois inteiros de n−bits é proporcional a n (O(n)). Isto significa que, se somar dois inteiros de n bits leva um tempo t, então a soma de dois inteiros de 2n bits leva um tempo 2t. Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 16/2 A LGORITMO PARA M ULTIPLICAÇÃO DE I NTEIRO Consideremos agora a multiplicação de dois inteiros a e b de n bits. Usando a propriedade distributiva, vemos que: ab = a(b0 20 + b1 21 + · · · + bn−1 2n−1 ) = a(b0 20 ) + a(b1 21 ) + · · · + a(bn−1 2n−1 ). Note que: abj = a se bj = 1 e abj = 0 se bj = 0 Além disso, cada vez que multiplicamos um termo por 2, “rotamos” a sua expansão binária um bit para a esquerda e colocamos um 0 na posição mais a direita da expansão binária. Obtemos então (abj )2j “rotando” a expansão binária de (abj ) j vezes para a esquerda, acrescentando j 00 s na direita da expansão. Finalmente, obtemos ab somando os n inteiros abj 2j , j = 0, 1, 2, · · · , n − 1 Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 17/2 A LGORITMO PARA M ULTIPLICAÇÃO DE I NTEIRO O pseudo-código a seguir acha a expansão binária (sn sn−1 · · · s1 s0 )2 da multiplicação da expansão binária de dois inteiros a e b. Algoritmo 3: Multiplicação de Inteiros procedure multiply(a,b:positive integer) {the binary expansions of a and b are (an−1 an−2 · · · a1 a0 )2 and (bn−1 bn−2 · · · b1 b0 )2 c := 0 for j = 0 to n − 1 begin if bj = 1 then cj := a “rotado” j vezes else cj := 0 end { c0 , c1 , · · · , cn−1 são os produtos parciais p := 0 for j = 0 to n − 1 p := add(p, cj ) {p é o valor de ab } Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 18/2 A LGORITMO PARA M ULTIPLICAÇÃO DE I NTEIRO Exemplo 5: Multiplique a = (110)2 e b = (101)2 . ab0 .20 = (110)2 .1.20 = (110)2 . ab1 .21 = (110)2 .0.21 = (0000)2 . e ab2 .22 = (110)2 .1.22 = (11000)2 . Basta agora somar (00110)2 + (00000)2 + (11000)2 , usando o algoritmo da soma: ab = (11110)2 . Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 19/2 A NÁLISE DO A LGORITMO Quantas adições e “rotações” de bits são necessárias no Algoritmo 3 para multiplicar dois inteiros? Como o Algoritmo 3 processa o produto de a e b somando os produtos parciais c0 , c1 , c2 , · · · , cn−1 . E como para obter cada cj são necessárias j “rotações”, então são necessárias no máximo: 0 + 1 + 2 + · · · + n − 1 “rotações”. Assim, o número de “rotações” é proporcional (ou da mesma ordem de grandeza) que n2 (O(n2 )). Para somar os produtos parciais cj requerem a soma de um inteiro de n-bits, um inteiro de n + 1-bits , · · · , e um inteiro de (2n)-bits, Sabemos que cada uma destas operações requer um número proporcional a n de operações de bits, Conseqüentemente, o número de operações de bits necessárias para multiplicar dois números é da ordem de grandeza de n2 (O(n2 )). Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 20/2 A LGORITMO PARA D IVISÃO DE I NTEIROS O pseudo-código a seguir calcula o quociente e o resto da divisão de um inteiro a por um inteiro positivo d. Algoritmo 4: Divisão de Inteiros (div e mod) procedure division(a: integer, d:positive integer) q := 0 r := |a| while r ≥ d begin r := r − d q := q + 1 end if a < 0 and r > 0 then begin r := d − r q := −(q + 1) end { q = a div d é o quociente, r = a mod d é o resto Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 21/2 E XPONENCIAÇÃO M ODULAR Em criptografia, é importante muitas vezes calcular de forma eficiente bn mod m, onde b, n e m são números inteiros grandes. Geralmente é impraticável calcular bn e então achar o seu resto quando dividido por m, pois bn será um número muito grande. Em vez disso, podemos usar um algoritmo que utiliza a expansão binária do expoente n = (ak−1 · · · a1 a0 )2 . O algoritmo acha sucessivamente b mod m, b2 mod m, b4 mod m, 2k−1 · · ·, b mod m e se vale da seguinte propriedade: c = (a.b)( mod m) c = (a( mod m)).(b( mod m))( mod m) Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 22/2 A LGORITMO PARA E XPONENCIAÇÃO M ODULAR Algoritmo 5: Exponenciação Modular procedure modular exponentiation(b: integer, n = (ak−1 ak−2 · · · a1 a0 )2 , m:positive integer) x := 1 power := b mod m for i := 0 to k − 1 begin if ai = 1 then x := (x.power) mod m power := (power.power) mod m end { x vale bn mod m } Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 23/2 A LGORITMO PARA E XPONENCIAÇÃO M ODULAR Exemplo 6: Use o Algoritmo 5 para calcular 26 44 mod 645. Inicialmente fazemos x = 1 e power = 2 mod 645 = 2. A expansão binária de 644 = (1010000100)2 . 2j O algoritmo calcula 2 mod 645 para j = 1, 2, · · · , 9 sucessivamente elevando ao quadrado e reduzindo modulo 645. Se aj = 1 (onde aj é o bit na j−ésima posição da expansão 2j binária de 644), ele multiplica o valor atual de x por 2 mod 645 e reduz o resultado módulo 645. Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 24/2 A LGORITMO PARA E XPONENCIAÇÃO M ODULAR Exemplo 6 i = 0 : Como a0 = 0, temos x = 1 e power = 22 = 4 mod 645 = 4; i = 1 : Como a1 = 0, temos x = 1 e power = 42 = 16 mod 645 = 16; i = 2 : Como a2 = 1, temos x = (1.16) mod 645 = 16 e power = 162 = 256 mod 645 = 256; i = 3 : Como a3 = 0, temos x = 16 e power = 2562 = 65536 mod 645 = 391; i = 4 : Como a4 = 0, temos x = 16 e power = 3912 = 152881 mod 645 = 16; i = 5 : Como a5 = 0, temos x = 16 e power = 162 = 256 mod 645 = 256; i = 6 : Como a6 = 0, temos x = 16 e power = 2562 = 65536 mod 645 = 391; i = 7 : Como a7 = 1, temos x = (16.391) mod 645 = 451 e power = 3912 = 152881 mod 645 = 16; i = 8 : Como a8 = 0, temos x = 451 e power = 162 = 256 mod 645 = 256; i = 9 : Como a9 = 1, temos x = (451.256) mod 645 = 1. Prof. Mauro Roisenberg - UFSC/CTC/INE/2008 – p. 25/2