Índice de conteúdos
Capítulo 1. Implementação de Algoritmos...1
1.Computação Numérica...1
2.Etapas na resolução de um problema...2
2.1.Definição do problema...2
2.2.Modelação matemática...2
2.3.Cálculo da solução numérica...2
2.3.1.Elaboração do algoritmo...2
2.3.2.Codificação do programa (implementação do algoritmo)...3
2.3.3.Processamento (execução) do programa...3
2.3.4.Exemplo...3
2.4.Análise dos resultados...4
3.Notação algorítmica...4
3.1.Estrutura do algoritmo...4
3.2.Variáveis e comentários...5
3.3.Expressões e comando de atribuição...5
3.3.1.Expressões aritméticas...5
3.3.2.Expressões lógicas...6
3.3.3.Expressões literais...7
3.4.Comandos de entrada e saída...7
3.5.Estruturas condicionais...7
3.5.1.Estrutura condicional simples...7
3.5.2.Estrutura condicional composta...7
3.6.Falha no algoritmo...9
3.7.Exemplo de algoritmo...9
4.Notação matemática...10
5.Complexidade computacional...11
6.Representação de números...13
6.1.Representação de números em diferentes bases...13
6.1.1.Representação de números inteiros e conversões de base...13
6.1.1.1.Representação de números inteiros...14
6.1.1.2.Conversão pelo método das divisões sucessivas...14
6.1.2.Representação de números reais e conversões de base...15
6.1.2.1.Representação em formato de ponto fixo...15
6.1.2.2.Representação no formato de ponto flutuante...16
6.1.2.3.Aritmética de ponto flutuante...17
6.1.3.Conversão de números inteiros da base b para a base decimal...19
6.1.3.1.Algoritmo de Horner...20
6.1.3.2.Divisão de Ruffini...21
6.1.4.Conversão de números fracionários da base b para a base decimal...21
6.1.4.1.Algoritmo de Horner...22
6.1.4.2.Divisão de Ruffini...22
6.1.5.Número binário infinito...23
6.2.Operações com números binários...24
6.2.1.Adição binária...24
6.2.2.Subtração binária...25
6.2.3.Multiplicação binária...26
6.2.4.Divisão binária...27
6.3.Representação de números em computadores digitais...27
6.3.1.Representação de números inteiros...27
6.3.2.Representação de números reais...31
-7.Erros...35
7.1.Fontes de erros e incertezas...35
7.2.Precisão e exatidão...36
7.3.Tipos de erros...37
7.3.1.Erro de formulação ou de modelação...37
7.3.2.Erros iniciais (incertezas dos dados do modelo)...37
7.3.3.Erro grosseiro...37
7.3.4.Erro de arredondamento...37
7.3.5.Erro de truncatura...38
7.4.Valores aproximados e erros...38
7.4.1.Erro absoluto...38
7.4.2.Erro relativo...39
7.4.3.Fórmula fundamental dos erros...40
7.4.4.Número de dígitos significativos...41
7.5.Erros de arredondamento...42
7.5.1.Arredondamento por defeito (ou corte do número)...43
7.5.2.Arredondamento simétrico...44
7.5.3.Erros de arredondamento na álgebra de ponto flutuante...45
7.5.3.1.Adição...46
7.5.3.2.Subtração...46
7.5.3.3.Multiplicação...47
7.5.3.4.Divisão...47
7.6.Erros de truncatura...47
7.6.1.Cálculo de valores de funções transcendentes...47
7.6.2.Discretização...48
7.6.3.Métodos iterativos...48
7.7.Condicionamento e estabilidade...51
7.8.Análise de erros...51
-Capítulo 1. Implementação de Algoritmos
1. Computação Numérica
Uma etapa intermédia importante durante a resolução de um problema envolve a elaboração de um algoritmo, o qual deverá ser posteriormente implementado numa linguagem de programação para se obter os resultados numéricos (solução do problema) num computador.
O Cálculo Numérico é uma metodologia para resolver problemas matemáticos por intermédio de um computador, sendo amplamente utilizado por engenheiros e cientistas. Uma solução via Cálculo Numérico é sempre numérico, enquanto que os métodos analíticos fornecem usualmente um resultado em termos de funções matemáticas. Muito embora uma solução numérica seja uma aproximação do resultado exato, ela pode ser obtida com um grau elevado de exatidão. Uma solução numérica é calculada mesmo quando o problema não tem solução analítica, facto comum nas equações diferenciais. O integral indefinido
∫
e−x2dxde grande utilidade na Estatística, é uma primitiva que não pode ser representada, explicitamente, por funções elementares. A área sob a curva descrita por e−x2de a até b pode ser determinada por meio de algoritmos numéricos que são aplicáveis a qualquer outro integrando, não sendo, portanto, necessário fazer substituições especiais ou mesmo a integração por partes para se obter o resultado.
Para computar (calcular por meio de um computador) um resultado numérico, são necessárias operações aritméticas (adição, subtração, multiplicação e divisão) e lógicas (comparação, conjunção, disjunção e negação). Considerando que estas são as únicas operações matemáticas que os computadores são capazes de realizar, então os computadores e o Cálculo Numérico formam uma combinação perfeita. Relembre-se que o primeiro computador de grande porte totalmente eletrónico, o ENIAC (Electronic Numerical Integrator And Calculator), projetado para realizar cálculos balísticos, e os atuais maiores supercomputadores no mundo inteiro estão dedicados a
2. Etapas na resolução de um problema
Dado um problema1 qualquer, como resolvê-lo no computador utilizando as técnicas de Cálculo
Numérico? Será mostrado, a partir de um exemplo simples, que a solução de um problema pode ser obtida em quatro etapas:
1. definição do problema, 2. modelação matemática, 3. cálculo da solução numérica e, 4. análise dos resultados.
2.1. Definição do problema
Nesta etapa, define-se qual é o problema real a ser resolvido. Seja, por exemplo, calcular
√
a , a > 0, usando apenas as 4 operações aritméticas.2.2. Modelação matemática
O problema real é transformado no problema original por meio de uma formulação matemática (denominado modelo matemático). No exemplo,
x=
√
a x2=a f( x) = x2−a = 0,o problema real, calcular
√
a , a > 0, foi transformado no problema original (modelo matemático) que é determinar a raiz de uma equação algébrica de grau 2.Geralmente, o problema original possui mais soluções que o problema real. Para este exemplo, +
√
a e −√
a são as duas raízes (soluções) da equação algébrica.2.3. Cálculo da solução numérica
Nesta etapa é feito a escolha do método numérico mais apropriado para resolver o problema original, obtido na modelação matemática. Depois de feita a escolha do método adequado, este é descrito através de um algoritmo, o qual é posteriormente implementado num computador com vista à obtenção dos resultados numéricos (soluções). Desta forma, esta etapa pode ser subdividida nas três fases seguintes (depois de efetuada a escolha do método):
a) elaboração do algoritmo, b) codificação do programa e,
c) processamento (execução) do programa.
2.3.1. Elaboração do algoritmo
Um algoritmo é a descrição de um conjunto de comandos que, quanto ativados (executados), resultam numa sucessão finita de acontecimentos. Em vez de se implementar um método diretamente numa linguagem de programação, é preferível descrevê-lo através de uma notação 1 Esta palavra deriva do nome do matemático árabe Mohammed ibu-Musa al-Khowarizmi ( 800 d.C.)
algorítmica. Desta forma, é possível abstrair-se dos detalhes da linguagem de programação do computador e concentrar-se apenas nos aspetos matemáticos do método.
Além do mais, a descrição do método numa notação algorítmica facilita a sua implementação em qualquer linguagem de programação. Na secção 3 é apresentada a notação algorítmica adotada para descrever os métodos numéricos incluídos neste documento.
2.3.2. Codificação do programa (implementação do algoritmo)
Nesta fase, o algoritmo é implementado na linguagem de programação escolhida. Como os aspetos matemáticos do método já foram pensados na fase de elaboração do algoritmo, agora apenas é necessário preocupar-se com os detalhes de implementação na linguagem adotada.
2.3.3. Processamento (execução) do programa
Finalmente, o código do programa obtido da implementação do algoritmo numa linguagem de programação deve ser executado pelo computador. Se for detetado algum erro lógico na fase de processamento, isto é, se a execução do programa produzir resultados inesperados, então deve-se retornar à fase de elaboração do algoritmo para o corrigir.
2.3.4. Exemplo
Para exemplificar a etapa de determinar a solução numérico do problema do cálculo de
√
a, será utilizado o método de Newton (descrito mais adiante) para calcular uma raiz de f( x) = x2−a = 0:xk+1 = xk− f(xk) f'(xk).
Substituindo f(x) e f'(x) na expressão acima, tem-se que xk+1 = xk−xk 2−a 2 xk = xk− xk 2 + a 2xk ou seja, xk+1 =
(
xk+ a xk)
× 1 2.Este é um processo iterativo para calcular
√
a a partir de um valor inicial x0, usando apenas as operações aritméticas. Para calcular√
9, usando x0 = 1, o processo produz os seguintes resultados:k xk xk - 3 0 1.0000 1 5.0000 2.0000 2 3.4000 0.4000 3 3.0235 0.0235 4 3.0001 0.0001
A coluna xk mostra as sucessivas aproximações de
√
9 a cada iteração k e a coluna xk-3 apresenta adiferença entre o valor aproximado xk e o valor exato 3.
2.4. Análise dos resultados
A adequação da solução numérica ao problema real é verificada nesta última etapa. Se a solução não se mostrar satisfatória, deve-se construir um novo problema original (modelo matemático) através de uma nova formulação matemática e determinar uma nova solução numérica.
Exemplo: Para o caso anterior (
√
a), se for atribuído o valor inicial x0 = -1 (ou qualquer x0 < 0), então o processo convergirá para -3, que, embora seja uma raiz de f( x) = x2−9 = 0, não é√
9.i xi xi - 3 0 -1.0000 1 -5.0000 -8.0000 2 -3.4000 -6.4000 3 -3.0235 -6.0235 4 -3.0001 -6.0001 5 -3.0000 -6.0000
Alguns modelos matemáticos podem produzir soluções que não têm sentido físico ou químico, como, por exemplo, tempo negativo, concentração complexa, etc. O objetivo da análise dos resultados é justamente discernir qual a solução válida para o problema real dentre as várias fornecidas pelo modelo matemático (se existirem algumas).
3. Notação algorítmica
A descrição de um algoritmo, através duma notação algorítmica, melhora o seu entendimento, pois apenas os aspetos do raciocínio matemático são realçados, sem ser necessário levar em consideração os detalhes de implementação de uma linguagem de programação.
3.1. Estrutura do algoritmo
Um algoritmo deve iniciar-se comAlgoritmo <nome-do-algoritmo>
e terminar com
fimalgoritmo Também
{ Objetivo: <objetivo-do-algoritmo> }
deve ser utilizado para descrever a finalidade do algoritmo. Os dados necessários para a execução de um algoritmo são requisitados por meio do comando
onde <lista-de-variáveis> são os nomes das variáveis, separadas por vírgulas, contendo os valores fornecidos. Não é necessário descrever exatamente como os valores dessas variáveis serão fornecidas ao algoritmo. Compete ao programador decidir durante a codificação do programa se os dados serão fornecidos interativamente pelo teclado, lidos de um ficheiro, passados como argumentos de um subprograma ou, até mesmo, definidos como constantes dentro do próprio programa.
Da mesma forma, os valores de interesse calculados pelo algoritmo são disponibilizados pelo comando
parâmetros de saída <lista-de-variáveis>
podendo a <lista-de-variáveis> ser ampliada ou reduzida pelo programados.
3.2. Variáveis e comentários
Uma variável corresponde a uma posição de memória do computador onde está, ou poderá estar, armazenado um determinado valor. As variáveis são representadas por identificadores que são cadeias de carateres alfanuméricos, podendo os elementos de vetores e matrizes ser referenciados por subscritos ou índices (por exemplo, vi ou v(i) e mij ou m(i,j)).
Um comentário é um texto inserido em qualquer parte o algoritmo para aumentar a sua clareza. Este texto deve ser delimitado por chavetas ( { <texto> } ), como por exemplo, { cálculo da raiz }.
3.3. Expressões e comando de atribuição
Existem três tipos de expressões: aritméticas, lógicas e literais, dependendo dos tipos dos operadores e das variáveis envolvidas.
3.3.1. Expressões aritméticas
Expressão aritmética é aquela cujos operadores são aritméticas e cujos operandos são constantes e/ou variáveis aritméticas. A notação é semelhante àquela utilizada para representar uma fórmula como, por exemplo,
√
(b2−4 a c), cos(2 + x) ou massa x velocidade.O símbolo é usado para atribuir o resultado de uma expressão a uma variável, ou seja, <variável> <expressão>
A tabela seguinte apresenta algumas funções matemáticas que podem ser usadas na elaboração dos algoritmos, pois consideram-se predefinidas.
Função Descrição Função Descrição
Trigonométricas sen tan seno tangente cos sec co-seno secante Exponenciais exp loge exponencial logaritmo natural log10 raiz2 logaritmo decimal raiz quadrada Numéricas abs arredonda max min valor absoluto arredonda para o inteiro
mais próximo maior valor menor valor quociente sinal resto trunca divisão inteira sinal(x) = 1 (se x > 0), 0 (se x = 0), -1 (se x <0) resto de divisão arredonda para baixo
3.3.2. Expressões lógicas
Uma expressão lógica é aquela cujos operadores são valores lógicos e cujos operandos são relações e/ou variáveis do tipo lógico. Uma relação é uma comparação realizada entre valores do mesmo tipo. A natureza da comparação é indicada por um operador relacional definido conforme a tabela seguinte, sendo que o resultado de uma relação ou de uma expressão lógica é verdadeiro ou
falso.
Operador relacional Descrição > ≥ < ≤ = ≠ maior que maior ou igual a menor que menor ou igual a igual a diferente de
A tabela seguinte mostra os resultados obtidos com os operadores lógicos, sendo que V significa verdadeiro e F falso. e b ou b a V F a V F a não a V F V F F F V F V V V F V F F V
3.3.3. Expressões literais
Uma expressão literal é formada por operadores literais e operandos, os quais são constantes e/ou variáveis do tipo literal.
O caso mais simples de uma expressão literal é uma constante literal, a qual é constituída por uma cadeia de carateres delimitada por aspas, por exemplo, mensagem “matriz singular”.
3.4. Comandos de entrada e saída
O comandoleia <lista-de-variáveis>
é usado para indicar que a <lista-de-variáveis> está disponível para leitura nalgum dispositivo externo. Por sua vez, o comando
escreva <lista-de-variáveis>
deve ser utilizado para indicar onde certos valores de interesse estão disponíveis no programa e podem ser escritos nalgum dispositivo externo. Compete ao programador decidir pela ampliação da <lista-de-variáveis> ou mesmo a omissão do comando escreva.
3.5. Estruturas condicionais
O uso de uma estrutura condicional torna possível a escolha dos comandos a serem executados quando certa condição for satisfeita ou não, possibilitando, desta forma, alterar o fluxo natural de comandos. Esta condição é representada por uma expressão lógica. As estruturas condicionais podem ser simples ou compostas.
3.5.1. Estrutura condicional simples
Esta estrutura apresenta a forma:
se <condição> então <comandos> fimse
Neste caso, a lista de <comandos> será executada se, e somente se, a expressão lógica <condição> tiver como resultado o valor verdadeiro.
3.5.2. Estrutura condicional composta
Quando houver duas alternativas possíveis, deve ser usada uma estrutura da forma seguinte:
se <condição> então <comandos_1> senão
<comandos_2> fimse
Se a expressão lógica <condição> tiver como resultado o valor verdadeiro, então a sequência <comandos_1> será executada e a sequência <comandos_2> não será executada. Por outro lado, se o resultado de <condição> for falso, então será a lista <comandos_1> a única a ser executada.
3.5.3. Estruturas de repetição
Uma estrutura de repetição faz com que uma sequência de comandos seja executada repetidamente até que uma dada condição de interrupção seja satisfeita. Existem, basicamente, dois tipos destas estruturas, dependendo se o número de repetições é indefinido ou definido.
Número indefinido de repetições
Este tipo de estrutura de repetição apresenta a forma:
repita <comandos_1> se <condição> então interrompa fimse <comandos_2> fimrepita <comandos_3>
O comando interrompa faz com que o fluxo de execução seja transferido para o comando imediatamente a seguir a fimrepita, Assim, as listas <comandos_1> e <comandos_2> serão repetidas até que a expressão lógica <condição> resulte no valor verdadeiro. Quando isso ocorrer, a repetição será interrompida (<comandos_2> não será realizada) e a lista <comandos_3>, a seguir a
fimrepita, será executada.
A forma repita-fimrepita é o caso geral de uma estrutura de repetição, Se a lista <comandos_1> não existir, ter-se-á uma estrutura de repetição com interrupção no início (estrutura enquanto). Da mesma forma, se não houver a lista <comandos_2>, então será uma estrutura com interrupção no final (estrutura repita-até).
Número definido de repetições
Quando se souber com antecedência quantas vezes a estrutura deve ser repetida, pode ser usado um comando de forma mais simples:
para <controle> <valor-inicial> até <valor-final> passo <delta> faça <comandos>
fimpara
Nesta estrutura, é atribuído inicialmente à variável <controle> o valor de <valor-inicial> e verificado se ele é maior do que o <valor-final>. Se for maior, a estrutura para-faça não será executada. Se for menor ou igual, então os <comandos> serão executados e a variável <controle>
será incrementada com o valor de <delta>. Novamente, é verificado se a variável <controle> é maior do que o <valor-final>; se não for maior, então os <comandos> serão executados e assim sucessivamente.
As repetições processam-se até que a variável <controle> seja maior do que o <valor-final>. Quando o incremento <delta> tiver valor 1, então o passo <delta> pode ser omitido da estrutura para-faça.
3.6. Falha no algoritmo
O comandoabandone
é usado para indicar que haverá uma falha evidente na execução do algoritmo, por exemplo, uma divisão por zero, ou o uso inapropriado de parâmetros. Neste caso, a execução será cancelada.
3.7. Exemplo de algoritmo
Dado um vetor x com n componentes (elementos), elaborar um algoritmo para determinar a média aritmética ̄x e o desvio padrão s dos seus elementos, sabendo que
̄ x = 1 n i=1
∑
n xi, e s =√
1 n −1(
i=1∑
n xi2−1 n(
i=1∑
n xi)
2)
. Algoritmo Média_desvio{ Objetivos: Calcular média aritmética e desvio padrão } parâmetros de entrada n, x
{ tamanho e elementos do vetor } parâmetros de saída Média, DesvioPadrão
Soma 0 Soma2 0
para i 1 até n faça Soma Soma + x(i) Soma2 Soma2 + x(i)2
fimpara
Média Soma / n
DesvioPadrão raiz2 ((Soma2 – (Soma2 / n)) / (n-1)) escreva Média, DesvioPadrão
4. Notação matemática
Definida a modelação matemática por meio de expressões aritméticas e lógicas, o passo seguinte é passar desta notação matemática para a notação algorítmica. Esta passagem é ilustrada pelos exemplos que se seguem.
Exemplo 1: implementar um algoritmo para calcular a norma-2 (norma Euclidiana) de um vetor x
de tamanho n, definida pela seguinte expressão: ∥x ∥2 =
√
∑
i=1 n
∣
xi∣
2.Algoritmo Norma2
{ Objetivos: Calcular a norma-2 (Euclidiana) de um vetor } parâmetros de entrada n, x
{ tamanho e elementos do vetor } parâmetros de saída N2
{ norma-2 do vetor } Soma 0
para i 1 até n faça
Soma Soma + (abs(x(i)))2
fimpara
N2 raiz 2(Soma) escreva N2 fimalgoritmo
Exemplo 2: implementar um algoritmo para calcular a norma- (norma de máxima magnitude) de
um vetor x de tamanho n, definida pela seguinte expressão: ∥x ∥∞ = max
1≤i≤n
∣
xi∣
. Algoritmo NormaInf{ Objetivos: Calcular a norma- de um vetor } parâmetros de entrada n, x
{ tamanho e elementos do vetor } parâmetros de saída Ninf
{ norma- do vetor } Ninf abs(x(1))
para i 2 até n faça
Ninf abs(x(i)) fimse fimpara escreva Ninf finalgoritmo
5. Complexidade computacional
É usual definir-se uma função de complexidade para medir o custo de execução de um algoritmo. Esta função tanto pode ser uma medida do tempo necessário para executar o algoritmo que resolve um problema de tamanho n, como o espaço de memória requerido para esta execução.
Como os algoritmos aqui estudados são polinomiais e as operações aritméticas têm diferentes tempos de execução pelo computador, a função de complexidade será definida, separadamente, para a adição/subtração, multiplicação e divisão.
A complexidade computacional de um algoritmo refere-se à estimativa do esforço computacional despendido para resolver o problema, sendo medido pelo número de operações aritméticas e lógicas efetuadas para resolver um sistema linear de ordem n.
Os problemas possuem complexidade computacional, podendo ser enquadrados em dois grupos: ➔grupo composto pelos algoritmos polinomiais, sendo a função de complexidade da forma:
O(cn pn + c
n-1 pn-1 + ... + c1 p1 + c0).
➔grupo formado pelos algoritmos exponenciais, sendo a função de complexidade da forma: O(cn), c > 1.
Exemplo:
Seja o polinómio de Lagrange de grau n definido da seguinte forma: Ln(x ) =
∑
i=0 n yi∏
j=0 j≠i n x−x j xi−xj. Expandindo, resulta a Expressão 1 seguinte:Ln(x) = y0× x −x1 x0−x1× x −x2 x0−x2 ×... × x −xn x0−xn + y1× x −x0 x1−x0 × x −x2 x1−x2 ×... × x −xn x1−xn + ... + yn× x −x0 xn−x0× x −x1 xn−x1×... × x −xn−1 xn−xn−1
cujo algoritmo é o seguinte:
Algoritmo Lagrange_Expressão_1
{ Objetivos: Interpolar usando polinómio de Lagrange } parâmetros de entrada m, x, y, z
{ número de pontos, abcissas } { ordenadas e valor a interpolar } parâmetros de saída r { valor interpolado }
r 0
para i 1 até m faça p y(i)
para j 1 até m faça
se i j então p p * ( (z – x(j)) / (x(i) – x(j)) ) fimse fimpara r r + p fimpara escreva r fimalgoritmo
Considerando que o número de pontos m usados na interpolação é igual a n+1, onde n é o grau do polinómio, então a complexidade computacional do algoritmo é:
Adições:
∑
i=1 m 2(m −1) + 1 = 2(m2−2m + m) = 2(n + 1)2−(n + 1) = 2n2+3n + 1 ; Multiplicações:∑
i=1 m (m −1) = m2−m = (n + 1)2−(n + 1) = n2+n ; Divisões:∑
i=1 m (m −1) = (m2−m) = (n + 1)2−(n + 1) = n2+nEstes resultados são resumidos na tabela seguinte (complexidade de interpolação de Lagrange).
Operações Complexidade
Adições 2n2 + 3n + 1
Multiplicações n2 + n
Divisões n2 + n
O polinómio de Lagrange também pode ser expandido de modo a resultar a Expressão 2 seguinte: Ln(x) = y0× (x −x1) × (x −x2) ×... × (x −xn)
+ y1× (x −x0) × (x −x2) ×... × (x −xn) (x1−x0) × (x1−x2) ×... × (x1−xn) + ...
+ y0× (x −x0) × (x −x1) ×... × (x −xn−1) (xn−x0) × (xn−x1) ×... × (xn−xn−1)
Ao analisar-se a complexidade computacional do algoritmo desta expressão, verifica-se que o número de adições é o mesmo e o de multiplicações é da mesma ordem (n2). No entanto, o número
de divisões utilizadas na Expressão 2 é de uma ordem grandeza a menos (n).
O polinómio de Lagrange serve para exemplificar que uma mesma notação matemática pode resultar em algoritmos de diferentes complexidades. Isto deve estar presente ao elaborar-se um algoritmo.
6. Representação de números
Nesta secção serão considerados aspetos básicos relativos ao cálculo numérico: a representação de números inteiros e de reais (em ponto flutuante) em código binário.
6.1. Representação de números em diferentes bases
Nesta secção serão discutidos alguns métodos para a mudança de base na representação de números, quer sejam inteiros ou reais. É comum, para grande parte dos computadores atuais utilizados na modelação computacional, o uso de uma base numérica distinta da base decimal. Em geral, os números são armazenados na base 2 (binária), existindo ainda plataformas que os armazenam na base 8 (octal) ou na base 16 (hexadecimal). A representação de números inteiros é ligeiramente distinta da representação de números reais.
6.1.1. Representação de números inteiros e conversões de base
De uma forma geral, um número inteiro N é representado, na base b, por um conjunto de dígitos ai, (i = 0,1,…, b-1 ), sendo que i assume um intervalo de valores determinado pela base em uso. A tabela seguinte indica estes valores para as bases mais utilizadas, inclusive para a base decimal.
b ai
2 0,1
8 0, 1, 2, 3, 4, 5, 6, 7 10 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
6.1.1.1. Representação de números inteiros
Há no mínimo duas formas de se representar um número inteiro N. O sistema posicional agrupa os dígitos na forma de uma sequência, na qual a magnitude da contribuição de cada dígito no número depende da posição relativa que este ocupa. Neste sistema, o número N é escrito como:
N = (an an-1 ... a1 a0)b
A contribuição de cada dígito para o valor de N fica explicitada na forma polinomial, onde N é escrito como (outra forma de representar um número):
N = an bn + a
n-1 bn-1 + ... + a1 b + a0
Até aqui, N tem sido tratado de uma forma abstrata. No entanto, por uma questão evolutiva, N tende a ser visto como um número na base 10 (decimal),
N = (an an-1 ... a1 a0) an an-1 ... a1 a0
Caso se passe a representar N sempre na base decimal, então deve-se abordar as outras representações do ponto de vista de conversões de ou para a base 10.
6.1.1.2. Conversão pelo método das divisões sucessivas
Considera-se apenas a conversão de um inteiro da base decimal (b = 10) para a base binária (b = 2), uma vez que esta será a representação mais provável num computador. Para realizar-se esta conversão de uma maneira prática, pode-se usar o método das divisões sucessivas, no qual N e os sucessivos quocientes qi são divididos por 2, sendo guardados os restos ri = 0,1 até que o último quociente seja qn = 0,1:
N = 2 q1 + r0; q1 = 2 q2 + r1; q2 = 2 q3 + r2; ... ; qn-1 = 2 qn + rn-1 O último quociente (qn) somente será 0 se N = 0. Então,
N = (qn rn-1 ... r1 r0)2 ou
N = qn 2n + r
n-1 2n-1 + rn-2 2n-2 + ... + r1 21 + r0 20
O mesmo método pode ser utilizado para converter N para qualquer base b; divide-se N e os sucessivos quocientes qi por b até que o último quociente seja um inteiro 0 ≤ qn ≤ b-1:
N = b q1 + r0; q1 = b q2 + r1; q2 = b q3 + r2; ... ; qn-1 = b qn + rn-1
O último quociente (qn) somente será 0 se N = 0. Então, N = (qn rn-1 ... r1 r0)b
ou
N = qn bn + r
6.1.2. Representação de números reais e conversões de base
Neste momento, é importante conhecer como os números reais podem ser armazenados num computador. Um número pode ser representado de duas formas:
➔ com ponto fixo, por exemplo, 12.34
➔ com ponto flutuante (ou vírgula flutuante), por exemplo, 0.1234x102.
6.1.2.1. Representação em formato de ponto fixo
Dado um número real X, este possui uma parte inteira Xi e uma parte fracionaria Xf = X - Xi. Desta forma, para se converter este número X na base binária utiliza-se o método das divisões sucessivas para Xi, enquanto que para Xf usa-se o método das multiplicações sucessivas: multiplica-se Xf por 2, extraindo-se a parte inteira do resultado (a qual pode ser 0); o restante é novamente multiplicado por 2, repetindo-se o processo até que o resto fracionário seja 0 ou que se obtenha um padrão repetitivo, em cujo caso o número fracionário será periódico. Este método será ilustrado com dois exemplos.
Exemplo 1: Seja Xf = 0.8125, então
0.8125 x 2 = 1.6250; 0.6250 x 2 = 1.2500; 0.2500 x 2 = 0.5000; 0.5000 x 2 = 1.0000 Ou seja,
0.8125 = (0.1101)2 .
Exemplo 2: Considere o número Xf = 0.1
Neste caso,
0.1 x 2 = 0.2; 0.2 x 2 = 0.4; 0.4 x 2 = 0.8; 0.8 x 2 = 1.6; 0.6 x 2 = 1.2; 0.2 x 2 = 0.4; ... e o processo de multiplicações sucessivas repete a sequencia de dígitos 0011 ad infinitum. Portanto,
0.1 = (0.0001100110011...)2 .
Este exemplo mostra a dificuldade de se obter a representação de um número fracionário noutra base.
Estes exemplos mostram que num computador, onde o espaço para representação de um número é finito, estes números terão que ser arredondados.
A forma polinomial de um número fracionário é dada por: Xf = 1 2-1 +
2 2-2 + 3 2-3 + ...
Portanto, um número real X = Xi + Xf pode ser representado na base 2 por X = an 2n + a
n-1 2n-1 + an-2 2n-2 + ... + a1 21 + a0 20 + 1 2-1 + 2 2-2 + 3 2-3 + ...
6.1.2.2. Representação no formato de ponto flutuante
A forma geral de representação de um número real de ponto flutuante é semelhante à notação científica:
d1d2d3... dp×be,
onde dk (k = 1,2,...,p) são os dígitos da parte fracionária (com 0 ≤ dk ≤ b-1, d1 ≠ 0), b é o valor da base (geralmente 2, 10 ou 16), p é o número de dígitos e e é um expoente inteiro. Deste modo, um número de ponto flutuante é composto por três partes: o sinal, a parte fracionária (denominada também de significando ou mantissa) e o expoente. Estas três partes têm um comprimento total fixo que depende do computador e do tipo de número: precisão simples, dupla ou estendida.
Seja um hipotético computador com dois dígitos (p = 2), base b = 2 e expoente e {-1, 0, 1, 2}. Como os números reais são normalizados, isto é, d1 ≠ 0, todos eles serão da forma:
.102×2e ou .112×2e, e =−1, 0, 1,2.
Considerando a conversão de binário para decimal de um número menor do que 1, .102 = 1 × 2−1+0 × 2−2 = 1/2 + 0 = 1/ 2, e
.112 = 1 × 2−1+1 × 2−2 = 1/2 + 1/4 = 3/ 4,
então, os únicos números positivos representáveis neste computador são:
.102×2−1 = 1/2 × 1/ 2 = 1/ 4 .112×2−1 = 3/ 4 × 1/2 = 3/ 8 .102×20 = 1/2 × 1 = 1/2 .112×20 = 3/ 4 × 1 = 3/ 4 .102×21 = 1/ 2 × 2 = 1 .112×21 = 3/ 4 × 2 = 3/2 .102×22 = 1/ 2 × 4 = 2 .112×22 = 3/ 4 × 4 = 3
O zero é representado de uma forma especial: todos os dígitos dk da mantissa e do expoente são nulos (002 x 20). O mais importante a reter relativamente aos números de ponto flutuante é que
eles são discretos e não contínuos como um número real definido na Matemática.
O conceito de existir sempre um número real entre dois números reais quaisquer não é válido para os números de ponto flutuante. As consequências da falha deste conceito podem ser desastrosas, como se poderá verificar no exemplo seguinte: considere a representação binária
0.610 = 0.100110011001...2 e 0.710 = 0.1011001100110...2.
Se estes dois números forem armazenados naquele hipotético computador (com dois dígitos para a mantissa), eles serão igualmente representados por: .102 x 20. Isto significa que tanto 0.610 como
0.710 são vistos como 0.510 por aquele computador. Esta é uma grande causa de erro de arredondamento nos processos numéricos, como será visto mais adiante neste documento.
Por outro lado, como a forma de representação (número de dígitos da mantissa) de um número de ponto flutuante pode ser diferente entre os fabricantes do computadores, um mesmo programa implementado em computadores que utilizam formatos diferentes pode fornecer resultados diferentes. O formato utilizado pela maioria dos computadores é o proposto pelo IEEE (Institute of Electrical and Electronics Engineers), o qual é apresentado na tabela que se segue.
Propriedade Precisão
Simples Dupla Estendida
Comprimento total 32 64 80 bits na mantissa 23 52 64 bits no expoente 8 11 15 base 2 2 2 expoente máximo 127 1023 16383 expoente mínimo -126 -1022 -16382 maior número 3.40 x 1038 1.80 x 10308 1.19 x 104932 menor número 1.18 x 10-38 2.123 x 10-308 3.36 x 10-4932 dígitos decimais 7 16 19
6.1.2.3. Aritmética de ponto flutuante
Se uma operação aritmética resultar num número que seja maior, em valor absoluto, que o maior número representável, ocorrerá um overflow. Se, por outro lado, resultar num número que seja menor, em valor absoluto, que o menor número representável diferente de zero, ocorrerá um underflow. O modo de tratar overflow e underflow dependerá do compilador utilizado para gerar o programa executável.
A seguir, será mostrado a precisão das operações numéricas envolvendo números de ponto flutuante. Para tal, será utilizado um outro hipotético computador com dois dígitos (p = 2), base b = 10 (para facilitar o entendimento) e expoente e {-5, …, 5}: d1d2 x 10e.
Quando dois números são somados ou subtraídos, os dígitos do número de menor expoente devem ser deslocados de modo a alinhar as casas decimais. O resultado é, então, arredondado para dois dígitos para caber na mantissa de tamanho p = 2. Depois disto, o expoente é ajustado de forma a normalizar a mantissa (d1 ≠ 0).
Exemplo 1: 4.32 + 0.064
Os números são armazenados no formato especificado, as casas decimais são alinhadas e a operação de adição é efetuada. O resultado é arredondado para dois dígitos é o seguinte:
4.32 + 0.064 = .43 x 101 + .64 x 10-1 = .43 x 101
+ .0064 x 101
= .4364 x 101
Exemplo 2: 372 - 371
Os números são armazenados no formato especificado, as casas decimais são alinhadas e a operação de adição é efetuada. O resultado é arredondado para dois dígitos é o seguinte:
372 - 371 = .37 x 103 + .37 x 103 = .37 x 103
- .37 x 103
= .00 x 103
.00 x 100.
O resultado da subtração é 0 em vez de 1. A perda de precisão quando dois números aproximadamente iguais são subtraídos é a maior fonte de erro nas operações de ponto flutuante.
Exemplo 3: 691 + 2.71
Os números são armazenados no formato especificado, as casas decimais são alinhadas e a operação de adição é efetuada. O resultado é arredondado para dois dígitos é o seguinte:
691 + 2.71 = .69 x 103 + .27 x 101 = .69 x 103
+ .0027 x 103
= .6927 x 103
.69 x 103.
O resultado da adição é 690 em vez de 693.71. O deslocamento das casas decimais de 2.71 causou uma perda total dos seus dígitos durante a operação.
Exemplo 4: 1234 x 0.016
Os números são armazenados no formato definido e a multiplicação é efetuada utilizando 2p = 4 dígitos na mantissa. O resultado é arredondado para dois dígitos e normalizado:
1234 x 0.016 = .12 x 104 x .16 x 10-1 = .12 x 104
x .16 x 10-1
= .0192 x 103
.19 x 102.
O resultado da multiplicação é 19 em vez de 19.744.
Exemplo 5: 875 x 3172
Os números são armazenados no formato definido e a multiplicação é efetuada utilizando 2p = 4 dígitos na mantissa. O resultado é arredondado, normalizado e, como o expoente e = 7 > 5 (máximo definido para este hipotético computador), então ocorre overflow:
875 x 3172 = .88 x 103 x .32 x 104 = .88 x 103
x .32 x 104
= .2816 x 107
overflow (e {-5, …, 5}).
Exemplo 6: 0.00183 492
Os números são armazenados no formato definido e a divisão é efetuada utilizando 2p = 4 dígitos na mantissa. O resultado é arredondado para dois dígitos e normalizado:
0.00183 492 = .18 x 10-2 .49 x 103 = .18 x 10-2
.49 x 103
= .3673 x 10-5
.37 x 10-5.
O erro relativo desse resultado foi de aproximadamente 0,52%.
Exemplo 7: 0.0064 7312
Os números são armazenados no formato definido e a divisão é efetuada utilizando 2p = 4 dígitos na mantissa. O resultado é arredondado, normalizado e, sendo o expoente e = -6 < -5, então ocorre underflow:
0.0064 7312 = .64 x 10-2 .73 x 104 = .64 x 10-2
.73 x 104
= .8767 x 10-6
underflow (e {-5, …, 5}).
O resultado da divisão é um valor inferior ao menor número representável por este comutador (por definição, e {-5, …, 5}), sem considerar o zero, que tem uma representação especial.
Uma das causas de se cometer erros quando se usa um computador deve-se à conversão de base. Geralmente, um número é fornecido ao computador na base 10 e, no entanto, ele é armazenado na base 2.
Quando os números são inteiros, a representação é exata, como, por exemplo, 4410 = 1011002. No entanto, um número com parte decimal pode resultar num número binário com infinitos dígitos (0.410 = 0.01100110...2) que têm que ser arredondados para o armazenamento num formato de ponto flutuante.
6.1.3. Conversão de números inteiros da base b para a base decimal
Para introduzir a conversão para a base decimal, será usada novamente a base binária como um primeiro exemplo. Seja o número N, representado na base binária por
N = (am am-1 ... a1 a0)2
a sua representação na base decimal pode ser obtida simplesmente pela soma do polinómio
N = am 2m + a
m-1 2m-1 + ... + a1 2 + a0
6.1.3.1. Algoritmo de Horner
O número N pode ser obtido na base decimal através do cálculo da sequência:
bm = am bm-1 = am-1 + 2 x bm bm-2 = am-2 + 2 x bm-1 ... ... b1 = a1 + 2 x b2 b0 = a0 + 2 x b1 e então, N = b0
Exemplo: seja o número (11101)2. Aplicando o algoritmo de Horner:
b4 = a4 = 1 b3 = a3 + 2 x b4 = 1 + 2 x 1 = 3 b2 = a2 + 2 x b3 = 1 + 2 x 3 = 7 b1 = a1 + 2 x b2 = 0 + 2 x 7 = 14 b0 = a0 + 2 x b1 = 1 + 2 x 14 = 29 portanto, (11101)2 = 2910
Esta metodologia pode ser generalizada para converter qualquer número inteiro na base b para a base decimal. Considere o número
N = (am am-1 ... a1 a0)b
a sua representação na base decimal pode ser obtida da seguinte forma:
cm = am cm-1 = am-1 + b x cm cm-2 = am-2 + b x cm-1 ... ... c1 = a1 + b x c2 c0 = a0 + b x c1 e então, N = c0
6.1.3.2. Divisão de Ruffini
É equivalente ao método anterior, diferindo apenas na disposição dos coeficientes ai e bi:
am am-1 ... a2 a1 a0
2 2 x bm ... 2 x b3 2 x b2 2 x b1
bm bm-1 ... b2 b1 b0
e então,
N = b0
Exemplo: seja o número (11101)2. Aplicando a Divisão de Ruffini:
a4 a3 a2 a1 a0 1 1 1 0 1 2 2 x b2 x 14 2 x b2 x 33 2 x b2 x 72 2 x 142 x b1 b4 b3 b2 b1 b0 1 3 7 14 29 portanto, (11101)2 = 2910
Esta metodologia pode ser generalizada para converter qualquer número inteiro na base b para a base decimal. Considere o número
N = (am am-1 ... a1 a0)b
a sua representação na base decimal pode ser obtida da seguinte forma:
am am-1 ... a2 a1 a0
2 b x cm ... b x c3 b x c2 b x c1
cm cm-1 ... c2 c1 c0
e então,
N = c0
6.1.4. Conversão de números fracionários da base b para a base decimal
Considere um número fracionário com representação finita na base binária: Xf = (0.a1a2…an)2 .
O seu valor na base decimal será dado por Xf = 1 2-1 +
2 2-2 + … + n 2-n
Esta soma pode ser calculada diretamente ou utilizando qualquer um dos dois métodos enunciados na secção anterior (Algoritmo de Horner e Divisão de Ruffini) com algumas modificações.
6.1.4.1. Algoritmo de Horner
No caso de um número fracionário na base 2, o algoritmo fica
bn = an bn-1 = an-1 + (1/2) x bn bn-2 = an-2 + (1/2) x bn-1 ... ... b2 = a2 + (1/2) x b3 b1 = a1 + (1/2) x b2 b0 = (1/2) x b1 e então, N = b0
Exemplo: converter o número (0.10111)2. Aplicando o algoritmo, fica:
b5 = a5 = 1 b4 = a4 + (1/2) x b5 = 1 + (1/2) = 3/2 b3 = a3 + (1/2) x b4 = 1 + (3/4) = 7/4 b2 = a2 + (1/2) x b3 = 0 + (7/8) = 7/8 b1 = a1 + (1/2) x b2 = 1 + (7/16) = 23/16 b0 = (1/2) x b1 = (1/2) x (23/16) = 23/32 portanto, (0.10111)2 = 23/32 = 0.71875 6.1.4.2. Divisão de Ruffini
No caso de um número fracionário na base 2, o algoritmo fica
an an-1 ... a2 a1
1/2 (1/2) x bm ... (1/2) x b3 (1/2) x b2 (1/2) x b1
bn bn-1 ... b2 b1 b0
e então,
Exemplo: Converter o número (0.10111)2 . Aplicando o algoritmo, fica:
a5 a4 a3 a2 a1 1 1 1 0 1 1/2 (1/2) x b5 (1/2) x b4 (1/2) x b3 (1/2) x b2 (1/2) x b1 (1/2) x 1 (1/2) x (3/2) (1/2) x (3/4) (1/2) x (7/8) (1/2) x (23/16) b5 b4 b3 b2 b1 b0 1 3/2 7/4 7/8 23/16 23/32 portanto, (0.10111)2 = 23/32 = 0.71875 6.1.5. Número binário infinito
Uma outra situação que pode ocorrer é quando o número binário for infinito, por exemplo, através de uma sequência de dígitos periódicos:
Xf=(0, α1α2... αnβ1β2...βm)2
onde β1β2... βm indica que a sequência de dígitos β1β2... βm se repete ad infinitum. Na base decimal, tal número é dado por
Xf = 1 2-1 + 2 2-2 + … + n 2-n + b1 2-n-1 + b2 2-n-2 + … + bm 2-n-m + + b1 2-n-m-1 + b 2 2-n-m-2) + … + bm 2-n-2m + + b1 2-n-2m-1 + b 2 2-n-2m-2 + … + bm 2-n-3m + + ...
Observa-se que este número pode ser escrito como Xf = 1 2-1 + 2 2-2 + … + n 2-n + ( b1 2-1 + b2 2-2 + … + bm 2-m ) 2-n + + ( b1 2-1 + b 2 2-2 + … + bm 2-m) ) 2-n-m + + ( b1 2-1 + b 2 2-2 + … + bm 2-m ) 2-n-2m + + … Ou seja, Xf = 1 2-1 + 2 2-2 + … + n 2-n + ( b1 2-1 + b2 2-2 + … + bm 2-m ) 2-n ( 1 + 2-m + 2-2m + … )
Usando agora a identidade, 1 1−x = 1 + x + x 2 + x3 + ...(para |x| < 1) tem-se 1 + 2−m + 2−2m + 2−3m + ... = 1 1 −2−m = 2m 2m−1 (fazendo x = 2 -m),
obtendo-se
Xf=α12−1 + α22−2 + ... + αn2−n+
(
β12−1 + β22−2 + ... + βm2−m)
2m−n
2m−1 As duas expressões entre parênteses têm a mesma forma e podem ser calculadas diretamente usando qualquer um dos métodos descritos anteriormente.
Em geral, se o número fracionário tem representação infinita periódica na base b,
Xf=α1b−1 + α2b−2 + ... + αnb−n+
(
β1b−1 + β2b−2 + ... + βmb−m)
bm−n bm−1 onde as expressões entre parênteses podem ser calculadas diretamente ou utilizando quaisquer um dos métodos descritos anteriormente.6.2. Operações com números binários
Como a maioria dos computadores usa a base b = 2, estes executam operações aritméticas com números que estão na representação binária. Para tal, as tabelas de operações que se seguem são automaticamente satisfeitas.
6.2.1. Adição binária
Uma adição no sistema binário é realizada da mesma forma que a adição no sistema decimal, lembrando que, no sistema binário, há apenas 2 dígitos. Esta operação é realizada de acordo com as seguintes regras (considerando os dois operados positivos):
0 + 0 = 0 0 + 1 = 1 1 + 0 = 1
1 + 1 = 0 (e “vai 1” para o dígito de ordem superior) 1 + 1 + 1 = 1 (e “vai 1” para o dígito de ordem superior)
Para somar números com mais de 2 algarismos, utiliza-se o mesmo processo de transporte para a coluna posterior, usado na adição decimal. Ter, no entanto, atenção aos limites das palavras.
Exemplo 1: 1012 + 0112 = 10002 (510 + 310 = 810) [1] [1] [1] 1 0 1 + 0 1 1 1 0 0 0 Exemplo 2: 012 + 112 = 1002 (110 + 310 = 410) [1] [1] 0 1 + 1 1 1 0 0
Exemplo 3: 10102 + 11112 = 110012 (1010 + 1510 = 2510) [1] [1] [1]
1 0 1 0
+ 1 1 1 1
1 1 0 0 1
Quando um dos operandos são números binários negativos, o processo a aplicar é o seguinte: ➔ dois operandos negativos: adicionam-se os dois considerando o valor absoluto de cada um
deles e atribui-se o sinal de negativo;
➔ um deles é negativo: verifica-se qual dos dois tem maior valor absoluto, subtraí-se o menor valor absoluto ao maior e, atribui-se o sinal do maior em valor absoluto.
6.2.2. Subtração binária
A subtração é análoga à adição, sendo realizada de acordo com as seguintes regras: 0 - 0 = 0
0 - 1 = 1 (e “pede emprestado 1” para o dígito de ordem superior) 1 - 0 = 1
1 - 1 = 0
Desta forma, a operação 0 - 1 resulta em 1, mas com o transporte de 1 para a coluna à esquerda, que deve ser acumulado ao subtraendo e, por consequência, subtraído do minuendo (em a-b, a o minuendo e b é o subtraendo). Exemplo 1: 1012 - 0112 = 0102 (510 - 310 = 210) [1] 1 0 1 - 0 1 1 0 1 0 Exemplo 2: 1112 - 1002 = 0112 (710 - 410 = 310) 1 1 1 - 1 0 0 0 1 1 Exemplo 3: 10102 - 10012 = 00102 (1010 - 910 = 110) [1] 1 0 1 0 - 1 0 0 1 0 0 0 1
6.2.3. Multiplicação binária
Procede-se como numa multiplicação no sistema decimal, de acordo com as seguintes regras: 0 x 0 = 0
0 x 1 = 0 1 x 0 = 0 1 x 1 = 1
Utiliza-se o mesmo método que a multiplicação decimal: deslocamentos e adições. O número maior deve ser colocado por cima do menor.
Exemplo 1: 1012 x 0112 = 0102 (510 x 310 = 1510) 1 0 1 x 0 1 1 1 0 1 1 0 1 + 0 0 0 0 1 1 1 1 Exemplo 2: 110102 x 0102 = 1101002 (2610 x 210 = 5210) 1 1 0 1 0 x 0 1 0 0 0 0 0 0 1 1 0 1 0 + 0 0 0 0 0 0 1 1 0 1 0 0 Exemplo 3: 10102 x 10002 = 10102 (1010 x 810 = 8010) 1 0 1 0 x 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 1 0 1 0 1 0 1 0 0 0 0
6.2.4. Divisão binária
A divisão binária usa o mesmo método que a divisão decimal: deslocamento e subtrações.
Exemplo 1: 1010102 1102 = 1112 (4410 410 = 1110) [1] [1] [1] 1 0 1 0 1 0 1 1 0 - 1 1 0 1 1 1 0 1 0 0 1 - 1 1 0 0 0 1 1 0 - 1 1 0 0 0 0
6.3. Representação de números em computadores digitais
Nesta secção serão apresentadas algumas das representações usadas para armazenar números inteiros e reais na memória de um computador. As representações de números inteiros e reais apresentadas na secção anterior não são suficientes; é necessário distinguir-se, por exemplo, o sinal do número. Como não existe a representação de um sinal + ou - na memória de um computador, o recurso utilizado é acrescentar um bit, para computadores binários, ao número para representar o sinal; este bit é denominado bit de sinal.
6.3.1. Representação de números inteiros
A representação mais direta de números inteiros é a denominada Sinal-Módulo (também denominada por Sinal-Magnitude). Nesta representação, o valor absoluto do número inteiro é obtido diretamente a partir dos algoritmos discutidos na secção anterior, enquanto que o sinal é representado por um dígito adicional colocado à esquerda do número.
Quando a representação é binária, o bit de sinal ocupa a posição do bit mais significativo. Então, supondo que a memória do computador dispõe de q dígitos para a representação, um número inteiro na base b será representado no computador através da seguinte sequência de dígitos:
aq-1 aq-2 ...a1 a0
sendo { a0, a1, …, aq-2, aq-1 } { 0, 1, …, b-2, b-1 } em que aq-1 representa o sinal do número. Esta sequência de dígitos é denominada palavra. Por exemplo, no sistema binário convenciona-se usar aq-1 = 0 para “+” e aq-1 = 1 para “-”.
A conversão do número internamente representado por aq-1 aq-2 ...a1 a0 para o sistema decimal é realizado através de uma fórmula semelhante à forma polinomial:
N = (−1)aq−1
×
∑
q−2
em que,
N o número inteiro na base decimal
q-2 é o índice do dígito mais à esquerda que representa o valor absoluto de N b a base, às vezes denominada de radix (um inteiro maior que 1)
ak um dígito válido na representação (0 ≤ ak < b), k = 0, 1, …, q-1
Os valores em questão para as quantidades expressas na fórmula anterior dependem da arquitetura e do compilador utilizado. Por exemplo, um dado compilador possui 4 modelos de representação de inteiros com 1, 2, 4 e 8 bytes, também denominados de espécies. Sendo para todos os casos b = 2, o valor absoluto do maior número inteiro que pode ser representado internamente para cada espécie Nmaxp , (p = 1, 2, 4, 8) é, a partir da fórmula anterior,
Nmaxp =
∑
k=0 8p−2 2k = 20+21+22+... + 28p−2 = 28p−1−1 ={
127 (p=1) 32767 (p=2) 2147483647 (p=4) 9223372036854775807 (p=8) A forma mais comum utilizada para representar números negativos em binário é tomando o dígito mais a esquerda que representar o sinal (0 representa sinal positivo e 1 sinal negativo)-27 26 25 24 23 22 21 20
sinal
Transformando o binário negativo em decimal: soma-se os bits “ligados” (com 1), considerando-se os valores de -27, 26, …, 20. Exemplos: 1 1 1 1 1 0 1 1 decimal -128 123 -5 (123-128) 1 1 0 1 0 1 1 1 decimal -128 87 -41 (87-128) 1 1 1 1 1 1 1 1 decimal -128 127 -1 (127-128)
Existem outras representações de números inteiros em computadores, como por exemplo as representações em complemento a (b-1) e em complemento a b.
A representação de números positivos em complemento é idêntica à representação em Sinal-Módulo. A representação dos números inteiros negativos é obtida efetuando-se: (base - 1) menos cada algarismo do número. Por exemplo, para calcular o complemento a (base - 1) do número -29710 (como a base é 10, então 10 - 1 = 9, e o complemento a (base -1) será complemento a 9); como 999 - 297 = 702, o complemento a 1 do número -297 é 702.
Para se obter o complemento a (b – 1) de um número binário, deve-se subtrair cada algarismo de 1 (b - 1 = 1); no entanto, como se trata de números binários é que, para efetuar esta operação, basta inverter todos os bits. Por exemplo, o complemento a 1 (C1) do número 00112 (usando 4 dígitos) é 11002, pois 11112 – 00112 = 11002.
A quantidade de números inteiros diferentes que se podem representar usando n posições num sistema de base b é bn. Por exemplo, na base 2, podem-se representar os seguintes números: 21 até
um dígito (0, 1), 22 até dois dígitos (00, 01, 10, 11), 23 números até três dígitos (000, 001, 010, 011,
100, 101, 110, 111), …
A tabela seguinte apresenta a representação em C1 dos números binários de 4 dígitos. Repare como o espaço de representação da base 2 com 4 dígitos está sendo usado na representação em C1 (note que há 2 representações para o zero).
Decimal
(positivo) (igual a sinal-módulo)Binário em C1 (negativo)Decimal Binário em C1
0 0000 0 1111 1 0001 -1 1110 2 0010 -2 1101 3 0011 -3 1100 4 0100 -4 1011 5 0101 -5 1010 6 0110 -6 1001 7 0111 -7 1000
A representação na base 10 com 3 dígitos varia de 000 a 999 (103 representações), representando
os números de -499 a -1 (faixa negativa que está compreendida entre 500 e 998) e de +1 a +499 (faixa positiva, que está compreendida entre 1 e 499). O zero tanto pode ser representado por 000 como por 999.
A faixa de representação em C1 dos números binários de n dígitos é a seguinte: ➔ menor inteiro negativo: -(2n-1 – 1),
➔ maior inteiro positivo: 2n-1 – 1.
Na aritmética em complemento a (base - 1), basta somar os números, sendo que um número negativo será representado por seu complemento a (base – 1). Por exemplo, a soma decimal de 123 com -418 é: Sinal-Módulo: -418 + 123 = -295 Complemento a 9 (base - 1): -418 é representado por 999 - 418 = 581 581 + 123 = 704
De notar que nesta representação, a subtração (ou soma de um número positivo com um número negativo) transforma-se numa soma em complemento; isto é, a soma dos complementos do número positivo com o número negativo. Portanto, uma subtração pode ser realizada simplesmente através da soma dos números “complementados”: manter o número se é positivo e complementar o número se é negativo; depois, é só somar.
Desta forma, pode-se constatar que o algoritmo da soma em complemento é muito mais simples que o da soma em sinal-módulo, uma vez que não requer nenhum teste. No entanto, continua-se com duas representações para o zero.
A representação dos números inteiros negativos em complemento a base é obtida subtraindo-se da base cada algarismo do número. Por exemplo, na base 10 com 3 dígitos: 1000 – x. Uma forma alternativa é subtrair cada algarismo de (base – 1), isto é, calcular o complemento a (base -1), e depois somar 1 ao resultado. Ou seja, encontramos o complemento a (base - 1) do número (o que facilita muito no caso dos números binários) e depois somamos 1 ao resultado.
Por exemplo, calcular o complemento a base (10) do número 29710 com 3 dígitos: ➔ usando C10: 1000 – 297 = 703;
➔ representar o número em C9 e somar 1 ao resultado: 999 – 297 = 702 702 + 1 = 703. Por exemplo, calcular o complemento a base (2) do número 00112 com 4 dígitos:
➔ usando C2: 10000 – 0011 = 01101;
➔ representar o número em C1 e somar 1 ao resultado: 1111 – 0011 = 1100 1100 + 0001 = 1101.
Desta forma, para representar um número binário negativo em complemento 2 (C2) consiste em subtrair cada algarismo de 1 (C1) e depois somar 1 ao resultado.
A tabela seguinte apresenta a representação em C2 dos números binários de 4 dígitos. Decimal
(positivo) (igual a sinal-módulo)Binário em C2 (negativo)Decimal Binário em C2
0 0000 -1 1111 1 0001 -2 1110 2 0010 -3 1101 3 0011 -4 1100 4 0100 -5 1011 5 0101 -6 1010 6 0110 -7 1001 7 0111 -8 1000
Comparando com a tabela anterior (para C1), nota-se que os números positivos têm a mesma representação de C1 e que o zero passou a ter apenas uma representação, o que permitiu representar mais um número (neste caso, mais um negativo pode ser representado).
A faixa de representação em C2 dos números binários de n dígitos é a seguinte: ➔ menor inteiro negativo: - 2n-1,
➔ maior inteiro positivo: 2n-1 – 1.
Na aritmética em complemento a base, basta somar os números, sendo que um número negativo será representado pelo complemento a base. Deve-se ter, no entanto, cuidado com a possibilidade de acontecer overflow. Em qualquer sistema em C2, existe sempre um limite para o tamanho dos números a serem representados. Por exemplo, quando se usam palavras de 4 bits (um para o sinal), o valor 9 não tem associado qualquer palavra; por isso não se consegue uma resposta certa para a soma de 5 com 4 (0101 + 0100 = 1001 que é -7). A adição de dois números no sistema de representação em C2 segue duas regras:
1. Somar os dois números e observar se ocorre transbordo (vai 1) sobre o bit de sinal e se ocorre o transbordo após o bit de sinal.
2. Se ocorrer um e somente um dos dois transbordos, então houve overflow; caso contrário o resultado da soma está dentro do campo de definição.
As vantagens do uso do complemento de 2 é que existe apenas um zero e que as regras para soma e subtração são as mesmas. A desvantagem é o fato de ser um código assimétrico: o número de representações negativas é maior que o número de representações positivas. Por exemplo, com 8 bits em complemento de 2 podem-ses representar os números decimais entre -128 e +127.
Exercícios. Considerando números binários com 4 bits (n = 4, um é o de sinal) e calcule as seguintes
somas e verifique se existe overflow:
1. 0101 + 0110 (5 + 6 = 11) 2. 0101 + 0010 (5 + 2 = 7) 3. 0101 + 1010 (5 – 6 = -1) 4. 0110 + 1011 (6 – 5 = 1) 5. 1011 + 1010 (-5 - 6 = -11)
A representação de um número inteiro num computador é exata. Operações aritméticas entre números inteiros também é exata, sob as seguintes condições:
1. o resultado não pode encontrar-se fora do intervalo de números inteiros que podem ser representados;
2. a divisão somente pode ser realizada entre números exatamente divisíveis, isto é, a parte fracionária deve ser nula.
6.3.2. Representação de números reais
A representação de números reais em computadores denomina-se por representação de ponto flutuante normalizado, na qual um número é representado internamente através de uma notação científica: um bit de sinal s (interpretado como positivo ou negativo), um expoente inteiro exato e
e uma mantissa inteira positiva M, sendo que apenas um número limitado de dígitos é permitido para e e M. Tomando todas estas quantidades juntas, estas representam o número
x = s × (0. d1d2... dn) ×be
o qual está escrito numa forma legível para os seres humanos. Além das quantidades já definidas na fórmula anterior, os dígitos d1, d2, …, dn são limitados pela base b (d1 0 e 1 di b-1, i = 1, …, n) e o expoente é limitado ao intervalo emin ≤ e ≤ emax . Adicionalmente, n ≥ 1 é denominado de número de dígitos do sistema e define o tamanho da mantissa M = 0. d1d2...dn.
O valor zero não pode ser normalizado e tem representação especial, com mantissa nula (todos dígitos iguais a zero) e expoente o menor possível (m–1). O conjunto formado pelo zero e por todos os números em notação de ponto flutuante é chamado Sistema de Ponto Flutuante na base b com n algarismos significativos, denota-se por F(b, n, emin, emax).
Contudo, um computador apenas pode representar os valores de e e M através de dígitos na base b. Um computador digital (b = 2), por exemplo, dispõe sempre de um tamanho de palavra finito, isto é, o número total de bits que podem ser utilizados para representar s (1 bit), a parte exponencial e a mantissa é sempre fixo, para um dado tipo de números reais. Um número real de precisão simples, por exemplo, é normalmente representado por uma palavra de 4 bytes (32 bits), sendo que 1 bit é utilizado para representar o sinal, enquanto que 8 bits são utilizados para representar a parte exponencial e os restantes 23 bits para representar a mantissa. Desta forma, tal número será representado na memória do computador como
x = s e7e6... e1e0d1d2... d22d23, onde
{
s ,e0,... ,e7,d1,...,d23}
∈{
0, 1}
.Exemplo: Considere-se dois números binários com 8 algarismos significativos em F(2, 8, -4, 3):
➔ n1 = 0 010 111001102 => (-1)0 x 22 x (0.11100110) = 3.59375 10
➔ n2 = 0 010 111001112 => (-1)0 x 22 x (0.11100111) = 3.60937510 .
Observe que, no sistema de representação utilizado, n1 e n2 são dois números consecutivos, ou seja, não podemos representar nenhum outro número que tenha valor intermediário. Portanto, por exemplo, a quantidade 3.60000 não tem representação exata neste sistema, sendo representada por n1 ou n2, o que gerará um erro, denominado Erro de Arredondamento. Assim, enquanto os números reais podem ser representados por uma reta contínua, em notação de ponto flutuante somente podemos representar pontos discretos da reta real.
A tabela que se segue ilustra representações de ponto flutuante para alguns números numa palavra típica de 32 bits (4 bytes), em F(2, 23, -128, 127).