Números no Computador
Muitos dos algoritmos de cálculo numérico, por uma questão prática, deverão ser executados numa máquina real.
Nestas máquinas, no entanto, a capacidade de memória para representação dos números é finita. Vários números reais (infinitos, de fato) terão a mesma representação no computador (ou calculadora), daí originando-se os
erros de arredondamentos. Vamos ver qual é a técnica usada atualmente para diminuir os erros de arredondamentos.
Representação de números inteiros numa base
Seja β>1 um número natural. Então podemos representar qualquer número inteiro k como a soma
k=sgn(k)∗a0β0+⋯+asβs
onde cada algarismo
aj representa um número natural entre
0 e
β−1. Só
as é diferente de zero. Esta representação é única.
A representação de
k na base
β é
k=±[as…a0]β
Deixando o sinal de
k de fora, para simplificar. Podemos calcular os algarismos do número daddo na base
β aplicando repetidas vezes o algoritmo da divisão.
Escrevendo
k=a0+β(a1+β(a2+⋯+βas)⋯))
vemos que
a0 é o resto da divisão
k//β,
a1 é o resto da divisão
(k−a0)//β e assim por diante.
Exemplo: 39=[100111]2
Representação de números fracionários e decimais numa base
Seja novamente β>1 um número natural.
Se x∈(0,1) então
x=b1β+⋯+bkβk+⋯
Diremos que
x=[0.b1b2…]β é a representação fracionária na base
β de
x. Quando não houver dúvidas de que base se trata, omite-se a base da notação!
Exemplo: 0.9=[0.1110011001100...]2
Uma função para colocar um número decimal na forma binária
In[1]:
|
# -*- coding: utf-8 -*-
"""
Spyder Editor
"""
def binario(a):
# da a representacao binaria do numero a
ParteInteira = int(a)
ParteDecimal = a-int(a)
# representacao binaria da parte inteira
# a lista seguinte guarda os dígitos da parte inteira
ListaDigitos=[]
while (ParteInteira > 0):
ListaDigitos.append(ParteInteira%2)
ParteInteira=ParteInteira//2
# lista dos digitos depois da virgula
ListaResto=[]
k=1
while ((ParteDecimal!=0)&(k<50)):
ListaResto.append(int(2*ParteDecimal))
ParteDecimal=2*ParteDecimal - int(2*ParteDecimal)
k=k+1
# produz a string de representacao:
i=len(ListaDigitos)-1
p1=""
while (i>=0):
p1=p1+str(ListaDigitos[i])
i=i-1
# Depois disso p1 tem a parte inteira
l=0
p2=""
while (l<len(ListaResto)):
p2=p2+str(ListaResto[l])
l=l+1
return p1+"."+p2
print (binario(21.75))
|
Representação em ponto flutuante
Consideramos uma base fixa β>1. Um número real α∈R positivo pode ser escrito nesta base como:
α=[ak⋯a0.b1b2⋯]β
Isto significa que:
α=akβk+⋯+a0+b1β+b2β2+⋯
Na equação acima, colocando
βk+1 em evidência temos:
α=(akβ+⋯+a0βk+1+b1βk+2+b2βk+3+⋯)×βk+1
ou ainda, lembrando da notação de um número numa base dada:
α=[0.ak⋯a0b1b2⋯]β×βk+1
Esta última fórmula é importante. O número real
α fica caracterizado por três dados:
- O número m=[0.ak⋯a0b1b2⋯]β∈(0,1) chamado de mantissa.
- O número e=k+1 chamado de expoente
- O sinal do número σ
Esta representação do número α como σm×βe chamaremos de representação normal em ponto flutuante na base β.
Em geral a base fica clara pelo contexto!
Números de máquina
Continuamos com a base fixa (β), mas na representação normal em ponto flutuante vamos admitir apenas números com a mantissa limitada a D dígitos e
o expoente limitado, em módulo, por um número inteiro M. O conjunto
M={[0.d1⋯dD]β×βe:|e|≤M}
é um conjunto de números de máquina definido pelos números
(β,D,M). Este é um conjunto finito com
(β−1)(β(D−1))(2M+1) elementos.
Vamos agora definir a função arredondamento, que é uma função sobrejetora
rd:R→M. Seja
α um número real;
se o expoente de
α for maior que
M não representamos o número. Senão tomamos sua mantissa e se o dígito
bd+1≥β/2 escolhemos
o menor número de máquina maior que
α para representá-lo. No caso de
bd+1<β/2 o representante será o maior número de máquina menor que
α.
Se denotarmos por α_ o truncamento do número α, isto é, o maior número de máquina menor que α. E
por ¯α o menor número de máquina maior que α. Temos que:
¯α−α_=βe−D
Com isto temos uma avaliação do erro absoluto e erro relativo do arredondamento:
|α−rd(α)|≤βe−D2
|α−rd(α)||α|≤β−D2