Praticando e aprendendo a mais antiga das ciências.

Precisão dos computadores

Em cálculos astronômicos a precisão necessária para a obtenção de uma determinada grandeza dependerá do tipo da grandeza. Por exemplo, se desejarmos calcular o horário em que um planeta estará nascendo para um local determinado, uma precisão de 0.001 graus ou mesmo 0.01 graus talvez seja suficiente. Isto ocorre pelo motivo da esfera celeste ter um movimento diurno aparente de um grau a cada quatro minutos. Isso corresponderia então a um erro aproximado de 0.01 graus a cada 0.04 minutos. Tomar precisões maiores neste exemplo seria desnecessário e produzira maior tempo gasto em processamento computacional. Caso o objetivo fosse determinar a posição de um planeta para um momento em que este ocultasse uma estrela, então uma precisão melhor que um segundo de arco seria necessária devido ao pequeno diâmetro angular dos planetas.

O problema da precisão de cálculos envolvendo computadores é muito mais complexo do que parece. Isto ocorre porque as linguagens de programação trabalham com certo número de dígitos significativos. Não devemos confundir quantidade de dígitos significativos com quantidades de casas decimais. Por exemplo, o número 0.00000531 possui 8 casas decimais mas apenas 3 dígitos significativos. Todos aqueles zeros à esquerda não contam como dígitos significativos. A precisão de uma medida depende da quantidade de dígitos significativos. Por exemplo a grandeza que possui uma medida avaliada em 0,003 unidades tem precisão menor que a grandeza 0,00300 unidades. A primeira tem apenas 1 dígito significativo enquanto a segunda possui 3 dígitos significativos (zeros a direita contam como dígitos significativos). Para se entender melhor sobre dígitos (ou algarismos) significativos recomendo a leitura de livros ou  apostilas de laboratório de Física que apresentam esse tema, ou acesse:

https://pt.wikipedia.org/wiki/Algarismo_significativo

Para se ter uma noção do perigo que isso representa em cálculos usando computadores considere, por exemplo, uma máquina que processe uma operação com apenas 6 dígitos significativos, então a operação 1 000 000 + 3 resultaria em 1 000 000. Outro exemplo seria a operação de dois valores com uma certa quantidade de dígitos significativos resultando num valor com muito menos dígitos significativos fornecendo um resultado com precisão muito menor que os valores usados na operação. Considere então a operação seguinte:

8.67346 – 8.67345 = 0.00001

Cada um dos valores usados na operação de subtração acima possui 6 dígitos significativos enquanto o resultado obtido possui apenas 1 dígito significativo. Outro grave problema é o do arredondamento de números. Suponha que os números do exemplo acima fossem arredondamentos dos valores com 8 dígitos significativos de 8.6734649 e 8.6734451. Assim a subtração destes valores seria 0.0000198 o qual arredondado para 1 dígito significativo daria o valor 0.00002 que seria o dobro do valor anterior. Isso poderia acarretar enormes erros em cálculos astronômicos e simulações.

Em matemática astronômica a precisão simples de 6 ou 8 dígitos significativos não são, geralmente, suficientes para cálculos com boa precisão. Para muitas operações é necessário que a máquina calcule com tantos dígitos significativos quanto requeira o resultado final.

 

Para saber qual é a precisão interna que a linguagem de programação (C++) trabalha, digite e execute o programa dado a seguir:

 

Programa 1:

——————————————————–

 

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
int j = 0;
double x = 1;

system(“cls”);
while ((x+1)!= x)
{
x = x*2;
j = j+1;
}

//  j*0.30103 é o número de dígitos significantes em um número decimal.
printf(“\n\nSignificantes bits: %d Digitos: %f\n\n”,j,j*0.30103);
system(“pause”);
return 0;
}

——————————————————–

Onde j é o número significante de bits na mantissa de números de ponto flutuante e j*0.30103 é o número de dígitos significantes em um número decimal e 0.30103 é o log102. Um computador com processador i3 usando a IDE Borland Turbo C++ 3.0 executado no DOSBox nos deu J = 64 e 19,3 dígitos. Este resultado serve apenas para aritmética simples, mas não para funções trigonométricas. Para testar a precisão do C++ com funções trigonométricas é só testar o comando:

printf(“%f”,4*atan(1));

o qual fornecerá o número pi (3.14159265358979) e daí você poderá verificar quantos dígitos significativos corretos ela te fornecerá. No Borland Turbo 3.0 C++ rodando no DOSBox obtive pi = 3.141593, o que nos deu sete dígitos significativos. O código a seguir pode ser implementado para esse teste:

 

Programa 2:

——————————————————–

#include<stdio.h>
#include<stdlib.h>
#include <math.h>

int main(void)
{
system(“cls”);
printf(“%f\n\n”,4*(atan(1))); // Imprime na tela o 4 x arctan  de 1 radiano
system(“pause”);
return 0;
}

——————————————————–

Erros de arredondamento podem acumular num dado processo de cálculo. A maioria dos erros acabam por não causar muitos transtornos mas em alguns processos aritméticos podem ser desastrosos. Veja o código do próximo exemplo:

Programa 3

——————————————————–

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
double x = 1.0/3.0;       // o ponto zero e necessario para que a variavel
int j;                                 // receba um valor de ponto flutuante.
system(“cls”);
printf(“Passo Valor”);
for (j = 1;j <= 30;j++)
{
x = (9*x + 1)*x – 1;      // Gera o valor 0.333333

printf(“\n%d %f”,j,x);
if (j == 20)      // Produz uma pausa para visualizacao dos dados
{
printf(“\n”);
system(“pause”);
}
}
printf(“\n\n”);
system(“pause”);

return 0;
}

——————————————————–

A operação x = (9*x + 1)*x – 1 retorna para x o próprio valor de x. Na maioria dos computadores este valor diverge quando ocorrem muitas iterações. No Turbo C++ até o passo 12 não houve problemas, no passo 19 o valor já está bastante modificado, a partir do passo 21 começa a divergir e do passo 29 já ultrapassa os limites de valores suportados pela linguagem de programação.

Outros desastres podem ocorrer quando fazemos operações aritméticas com computadores, por exemplo: se somarmos mil vezes o valor 0.1 devemos obter o valor 100. Digite o código do programa a seguir, que efetua essa operação, e verifique o resultado.

Programa 4

——————————————————–

#include<stdio.h>
#include<stdlib.h>

int main(void)
{
float x = 0.0;
int c;
system(“cls”);
for (c = 1;c <=1000; c++)
x += 0.1;
printf(“\n%f\n”,x);
system(“pause”);
return 0;
}

——————————————————–

O resultado impresso na tela do computador, com o Borland Turbo C++ 3.0, foi: 99.999046. Isso ocorre porque 0.1 é representado no computador por  valores na base 2 e 0.1 é traduzido para o computador como sendo 0.099999. É um valor muito próximo de 0.1, mas quando produzimos muitas iterações de cálculos esse valor pode causar diferenças significativas.

Podemos arredondar resultados quando isto for necessário, por exemplo: o valor 13.88 pode ser arredondado para 13.9 ou mesmo 14, não para 13. No entanto para o arredondamento de datas como setembro 13.88, este valor aponta para algum instante do dia 13 de setembro, isto é 0.88 dia após zero hora de 13 de setembro. Para o caso da ocorrência de um fenômeno em setembro 13.88 isto acontecerá no dia 13 e não no dia 14.

Arredondamentos de resultados devem levar em consideração a quantidade de algarismos significativos. Por exemplo: considere a fórmula de Müller para determinação da magnitude visual de Júpiter:

m = -8.93 +5*log(r*∆)

Onde r é a distância de Júpiter ao Sol e   ∆ é a distância de Júpiter a Terra, ambos em unidades astronômicas. Considere então que para uma determinada data r = 5.417149 e ∆ = 5.125382. O computador poderia fornecer o seguinte resultado: m = -1.712514898. Todavia todas essas casas decimais não são significativas visto que a constante -8.93 possui apenas duas casas decimais. Então a precisão dessa fórmula não é muito alta. Assim o resultado deveria ser expresso no máximo com duas casas decimais (ver teoria sobre operações com valores em algarismos significativos no link fornecido). Assim o resultado seria melhor expressado como m = -1.71.

Referências:

Meeus, Jean, Astronomical Algorithms, 2. Ed. Richmond, Virginia: Willmann-Bell, Inc, 1991.

Meeus, Jean, Astronomical Formulae for Calculatores, 3 Ed. Richmond, Virginia: Willmann-Bell, Inc, 1985.

<Anterior     Próxima>