Artigo: 125056 - Última revisão: quinta-feira, 24 de Fevereiro de 2005 - Revisão: 2.1

INFO: Precisão e precisão em cálculos Floating-Point

Dica do SistemaEste artigo aplica-se a um sistema operativo diferente do que está a utilizar. Foi desactivado o conteúdo do artigo, que pode não ser relevante para si.

Nesta página

Expandir tudo | Reduzir tudo

Sumário

Existem muitas situações em que precisão arredondamento, e precisão em cálculos de vírgula flutuante pode funcionar para gerar resultados surpreendente para o programador. Existem quatro regras gerais que devem ser seguidas:
  1. Um cálculo envolvendo simples e dupla precisão, o resultado não normalmente será mais preciso do que precisão único. Se for necessário precisão dupla, ter a certeza todos os termos no cálculo, incluindo constantes, são especificados na precisão dupla.
  2. Nunca partem do princípio que um valor numérico simples com precisão é representado no computador. Mais valores de vírgula flutuante não podem ser representados com precisão como um valor binário finito. Por exemplo 0,1 é.0001100110011... em binário (que repete sempre), pelo que não pode ser representada com exactidão completa num computador binário aritmético, que inclui todos os computadores.
  3. Nunca assumem que o resultado é preciso para a última casa decimal. Existem sempre pequenas diferenças entre a resposta "true" e o que pode ser calculado com precisão finito de qualquer unidade de processamento de ponto flutuante.
  4. Nunca compare dois valores de vírgula flutuante para ver se são iguais ou não igual. Esta é uma corollary a regra 3. Existe quase sempre vão ser pequenas diferenças entre os números "" será iguais. Em vez disso, verifique sempre se os números são quase iguais. Por outras palavras, verifique se a diferença entre eles é muito pequeno ou não significativos.

Mais Informação

Em geral, as regras descritas acima aplicam-se para todos os idiomas, incluindo C, C++ e integrador. Os exemplos abaixo demonstram algumas das regras utilizando FORTRAN PowerStation. Todos os exemplos foram compilados utilizando FORTRAN PowerStation 32 sem quaisquer opções, excepto para o último que é escrito em C.

Consulte o manual(s) FORTRAN fornecidos com o Microsoft FORTRAN para obter uma descrição das constantes numéricas e artigo 36068  (http://support.microsoft.com/kb/36068/EN-US/ ) para uma descrição da representação interna de valores de vírgula flutuante.

EXEMPLO 1

O primeiro exemplo demonstra duas coisas:

  • Que FORTRAN constantes são precisão simples por predefinição (C constantes são dupla precisão por predefinição).
  • Cálculos com os termos de precisão simples não são muito mais precisos do que cálculos em que todos os termos são precisão único.
Depois de ser inicializado com 1.1 (uma constante de precisão simples), y está como incorrecto como uma variável de precisão simples.
   x = 1.100000000000000  y = 1.100000023841858
				
o resultado da multiplicação de um valor de precisão simples por um valor de precisão dupla precisão é quase incorrecto como Multiplicar dois valores de precisão simples. Ambos os cálculos têm inúmeras vezes tanto erros como Multiplicar dois valores de precisão dupla.
   true = 1.320000000000000 (multiplying 2 double precision values)
   y    = 1.320000052452087 (multiplying a double and a single)
   z    = 1.320000081062318 (multiplying 2 single precision values)
				

Código de exemplo

C Compile options: none

       real*8 x,y,z
       x = 1.1D0
       y = 1.1
       print *, 'x =',x, 'y =', y
       y = 1.2 * x
       z = 1.2 * 1.1
       print *, x, y, z
       end
				

EXEMPLO 2

Exemplo 2 utiliza a equação quadratic. Demonstra a que mesmo dupla precisão cálculos não são perfeitos, e a que o resultado de um cálculo deve ser testado antes é dependia se erros pequenos podem ter resultados drásticas. A entrada da função de raiz quadrada no exemplo 2 apenas é ligeiramente muito negativa, mas ainda não é válido. Se os cálculos de precisão dupla não tinham pequenos erros, o resultado seria:
   Root =   -1.1500000000
				
em vez disso, gera o seguinte erro:
Run-time error M6201: MATEMÁTICO
-sqrt: erro de domínio

Código de exemplo

C Compile options: none

       real*8 a,b,c,x,y
       a=1.0D0
       b=2.3D0
       c=1.322D0
       x = b**2
       y = 4*a*c
       print *,x,y,x-y
       print "(' Root =',F16.10)",(-b+dsqrt(x-y))/(2*a)
       end
				

EXEMPLO 3

Exemplo 3 demonstra que devido a optimizações ocorrer mesmo se optimização não está activada, os valores podem temporariamente mantêm uma precisão mais elevada do que o esperado e não é muito recomendável com o teste dois valores de ponto flutuante para igualdade.

Neste exemplo, dois valores são iguais e não iguais. No primeiro se, o valor de Z continua na pilha do coprocessador e tem a mesma precisão como Y. X, por isso, não é igual Y e a primeira mensagem é impressa. Na altura do se segundo Z tinha de ser carregado a partir da memória e assim tivesse a mesma precisão e valor de X e a segunda mensagem também é impressa.

Código de exemplo

C Compile options: none

       real*8 y
       y=27.1024D0
       x=27.1024
       z=y
       if (x.ne.z) then
         print *,'X does not equal Z'
       end if
       if (x.eq.z) then
         print *,'X equals Z'
       end if
       end
				

EXEMPLO 4

A primeira parte do código de exemplo 4 calcula a diferença mais pequena possível entre dois números perto para 1.0. Isto é adicionando um único bit representação binária do 1.0.
   x   = 1.00000000000000000  (one bit more than 1.0)
   y   = 1.00000000000000000  (exactly 1.0)
   x-y =  .00000000000000022  (smallest possible difference)
				
algumas versões do FORTRAN arredondar os números na apresentação-os para que o inerente numérico imprecision não é tão óbvio. Este é o motivo x e y semelhantes a quando apresentada.

A segunda parte do código de exemplo 4 calcula a diferença mais pequena possível entre 2 números perto para 10.0. Novamente, isto é adicionando um único bit representação binária de 10.0. Repare que a diferença entre números junto 10 é maior do que a diferença próximo de 1. Demonstra o princípio geral que quanto maior for o valor absoluto de um número menor com precisão pode ser armazenado um determinado número de bits.
   x   = 10.00000000000000000  (one bit more than 10.0)
   y   = 10.00000000000000000  (exactly 10.0)
   x-y =   .00000000000000178
				
representação binária destes números também é apresentada para mostrar que diferem apenas um bit.
   x = 4024000000000001 Hex
   y = 4024000000000000 Hex
				
a última parte do código de exemplo 4 mostra que simples valores decimais não repetitivos, muitas vezes, podem ser representados em binário apenas por uma fracção de repetição. Neste incidente x = 1.05, que requer um factor de repetição CCCCCCCC....(Hex) na mantissa. Em FORTRAN, o último dígito "C" é arredondado para "D" para manter a exactidão mais elevada possível:
   x = 3FF0CCCCCCCCCCCD (Hex representation of 1.05D0)
				
mesmo depois do arredondamento, o resultado não seja perfeitamente preciso. Existe algum erro após o dígito menos significativo, que poderá constatar, removendo o primeiro dígito.
   x-1 = .05000000000000004
				

Código de exemplo

C Compile options: none

       IMPLICIT real*8 (A-Z)
       integer*4 i(2)
       real*8 x,y
       equivalence (i(1),x)

       x=1.
       y=x
       i(1)=i(1)+1
       print "(1x,'x  =',F20.17,'  y=',f20.17)", x,y
       print "(1x,'x-y=',F20.17)", x-y
       print *

       x=10.
       y=x
       i(1)=i(1)+1
       print "(1x,'x  =',F20.17,'  y=',f20.17)", x,y
       print "(1x,'x-y=',F20.17)", x-y
       print *
       print "(1x,'x  =',Z16,' Hex  y=',Z16,' Hex')", x,y
       print *

       x=1.05D0
       print "(1x,'x  =',F20.17)", x
       print "(1x,'x  =',Z16,' Hex')", x
       x=x-1
       print "(1x,'x-1=',F20.17)", x
       print *

       end
				

EXEMPLO 5

C, constantes flutuantes são duplica por predefinição. Utilize um "f" para indicar um valor de vírgula flutuante, tal como em "89.95f".
   /* Compile options needed: none
   */ 

   #include <stdio.h>

   void main()
   {
      float floatvar;
      double doublevar;

   /* Print double constant. */ 
      printf("89.95 = %f\n", 89.95);      // 89.95 = 89.950000

   /* Printf float constant */ 
      printf("89.95 = %f\n", 89.95F);     // 89.95 = 89.949997

   /*** Use double constant. ***/ 
      floatvar = 89.95;
      doublevar = 89.95;

      printf("89.95 = %f\n", floatvar);   // 89.95 = 89.949997
      printf("89.95 = %lf\n", doublevar); // 89.95 = 89.950000

   /*** Use float constant. ***/ 
      floatvar = 89.95f;
      doublevar = 89.95f;

      printf("89.95 = %f\n", floatvar);   // 89.95 = 89.949997
      printf("89.95 = %lf\n", doublevar); // 89.95 = 89.949997
   }
				

A informação contida neste artigo aplica-se a:
  • Microsoft FORTRAN PowerStation 1.0 Standard Edition
  • Microsoft Fortran PowerStation 1.0a para MS-DOS
  • Microsoft FORTRAN PowerStation 32
  • Microsoft Visual C++ 1.0 Professional Edition
  • Microsoft Visual C++ 1.5 Professional Edition
  • Microsoft Visual C++ 1.51
  • Microsoft Visual C++ 2.0 Professional Edition
  • Microsoft Visual C++ 4.0 Standard Edition
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 6.0 Enterprise Edition
  • Microsoft Visual C++ 5.0 Professional Edition
  • Microsoft Visual C++ 6.0 Professional Edition
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
Palavras-chave: 
kbmt kbcode kbinfo kblangc kblangfortran KB125056 KbMtpt
Tradução automáticaTradução automática
IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine translation ou MT), não tendo sido portanto revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 125056  (http://support.microsoft.com/kb/125056/en-us/ )