INFO: Precisão e rigor nos cálculos de vírgula flutuante

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
Sumário
Existem muitas situações em que precisão de arredondamento e precisão cálculos infloating-point podem trabalhar para gerar resultados que aresurprising para o programador. Existem quatro regras gerais que devem befollowed:
  1. Num cálculo que envolvam precisão simples e duplo, o resultado não normalmente será mais preciso do que a precisão único. Se for necessário dupla precisão, certifique-se de todos os termos no cálculo, incluindo constantes, são especificados no dupla precisão.
  2. Nunca partem do princípio de que um valor numérico simple com exactidão é representado no computador. Maior número de vírgula flutuante valores não podem ser representadas com precisão como um valor binário finito. Por exemplo. 1 é.0001100110011... em binário (repete-se sempre), pelo que não podem ser representada com exactidão completa num computador com o binário aritmético, que inclui todos os computadores.
  3. Nunca partem do princípio de que o resultado ser exacto com a última casa decimal. Existem sempre pequenas diferenças entre a resposta "true" e o que pode ser calculado com a precisão finita 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. Este é um corolário a regra 3. Quase sempre vão ser pequenas diferenças entre os números "devem" ser iguais. Em vez disso, sempre verificar se os números são praticamente iguais. Por outras palavras, verifique se a diferença entre eles for demasiado pequeno ou insignificante.
Mais Informação
Em geral, as regras de acima descritas é aplicável a todos os idiomas, incluindo C, C++ e o integrador. Os exemplos que se seguem demonstram algumas das usingFORTRAN regras PowerStation. Todas as amostras foram compiladas com FORTRANPowerStation 32 sem quaisquer opções, excepto o último, que iswritten no C.

Consulte os manuais de FORTRAN fornecidos com o Microsoft FORTRAN para adescription de constantes numéricas e artigo 36068 Para obter uma descrição da representação interna de valores de vírgula flutuante.

EXEMPLO 1

O primeiro exemplo demonstra duas coisas:

  • Que as constantes de FORTRAN são precisão simples por predefinição (C constantes são dupla precisão por predefinição).
  • Cálculos que contêm os termos de precisão simples não são muito mais precisos do que os cálculos em que todos os termos são precisão único.
Depois de ser inicializada com 1.1 (uma constante de precisão simples), o eixo dos YY é asinaccurate como uma variável de precisão simples.
   x = 1.100000000000000  y = 1.100000023841858				
O resultado da multiplicação um valor de precisão simples por um valor de doubleprecision exacto é quase tão incorrecto como multiplicando dois precisionvalues único. Ambos os cálculos têm milhares de vezes tanta valores de precisão dupla de asmultiplying duas de erro.
   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 quadrática. Este exemplo demonstra que até mesmo cálculos de doubleprecision não são perfeitos, e que o resultado da acalculation deve ser testado antes de é dependia se resultados drásticas de ter de pequenos erros. A entrada para a função de raiz quadrada no exemplo 2 isonly muito pouco negativo, mas não é ainda válida. Se os cálculos de doubleprecision não tinha ligeiros erros, o resultado seria:
   Root =   -1.1500000000				
Em vez disso, gera o seguinte erro:
tempo de execução erro M6201: MATEMÁTICA
-RAIZQ: 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 que ocorrem ifoptimization mesmo não está activada, valores podem reter temporariamente um higherprecision que o esperado, e que não é muito recomendável testar dois valores de vírgula flutuante de igualdade.

Neste exemplo, dois valores são iguais e não é igual. Se o primeiro, o valor de Z continua na pilha do coprocessador e tem sameprecision como Y. Não é igual a X, por conseguinte, Y e a primeira isprinted mensagem saída. No momento do segundo se, Z teve de ser carregada a partir de memoryand por conseguinte, a mesma precisão e valor de X e o segundo messagealso é impresso.

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 os menor possível differencebetween dois números perto 1.0. Isto acontece, adicionando um único bit a 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 números quando apresentá-los de modo que theinherent numérico imprecisão não é tão óbvio. Isto é por este motivo que x e y lookthe mesmo quando é apresentada.

A segunda parte do código de exemplo 4 calcula a possibledifference mais pequena entre os 2 números próximo 10.0. Novamente, fá-lo adicionando asingle bit para a representação binária do 10.0. Repare que os números differencebetween perto 10 é maior do que a diferença próximo de 1. Thisdemonstrates ao princípio geral que quanto maior for o valor absoluto de anumber, menos precisamente podem ser armazenados num determinado número de bits.
   x   = 10.00000000000000000  (one bit more than 10.0)   y   = 10.00000000000000000  (exactly 10.0)   x-y =   .00000000000000178				
Também é apresentada a representação binária destes números para mostrar diferentes thatthey em apenas um bit.
   x = 4024000000000001 Hex   y = 4024000000000000 Hex				
A última parte do código de exemplo 4 mostra que decimalvalues não repetitivos simples frequentemente pode ser representada em binário apenas por uma fracção de repetição. Inthis x caso = 1,05, o que requer uma repetição factor CCCCCCCC... (Hexadecimal) na mantissa. O último dígito "C" é arredondado por excesso para "D" de forma FORTRAN, manter a maior precisão possível:
   x = 3FF0CCCCCCCCCCCD (Hex representation of 1.05D0)				
Mesmo depois do arredondamento, o resultado não é preciso perfeitamente. Não existe someerror após ao 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				

AMOSTRA 5

C constantes flutuantes estão duplica por predefinição. Utilize um "f" para indicar o valor do flutuar, "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   }				

Aviso: Este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 125056 - Última Revisão: 09/27/2015 10:34:00 - Revisão: 3.0

Microsoft FORTRAN PowerStation 1.0 Standard Edition, Microsoft Visual C++ 1.5 Professional Edition, Microsoft Visual C++ 2.0 Professional Edition, Microsoft Visual C++ 5.0 Enterprise Edition, Microsoft Visual C++ 5.0 Professional Edition

  • kbcode kbinfo kblangc kblangfortran kbmt KB125056 KbMtpt
Comentários