Página 1 de 1

Erro do C (Herdado no xHarbour)

Enviado: 30 Jan 2008 15:41
por asimoes
Pessoal,

Verificando meus documentos sobre o clipper me deparei com um antigo erro bastante comentado e que vale apena exibi-lo para que ninguém se engane com comparações lógicas, uma parte do erro não se repete no xHarbour mas outra sim, vou deixar de lero-lero e mostrar o que acontece:

Código: Selecionar todos

FUNCTION MAIN
   CLS
   Var1 = 2045.18
   Var2 = 500
   Tot  = 2545.18

   // Assim dá erro: (Clipper e xHarbour)
   If Tot = (Var1 + Var2)
      ? "Igual"
   Else
      ? "Distinto"
   EndI

   // Assim dá certo: (Clipper e xHarbour)
   If STR(Tot) = STR((Var1 + Var2))
      ? "Igual"
   Else
      ? "Distinto"
   EndI

//                             No Clipper  No xHarbour
   ? int(1.14*100) //        = 113        = 114
   ? int(1.15*100) //        = 114        = 115
   ? int(1.16*100) //        = 115        = 116
   ? int(1.17*100) //        = 117        = 117

RETURN NIL
[]´s

Enviado: 30 Jan 2008 16:03
por Maligno
Tanto no Clipper quanto no XHarbour o erro se explica pela forma como são manipulados os números. Como se trata de ponto flutuante, apesar de visualmente ser tão simples pra nós vermos qual é o resultado, para a lógica do ponto flutuante não é tão simples assim. O número 1, por exemplo, não é 1 de fato. Assim como 2,5-0,5 não é 2. A representação do ponto flutuante é muito complexa. Por isso, quando comparar números em ponto flutuante, só há duas alternativas: a primeira você já mostrou, convertendo para strings. A segunda, muito usada em C, por exemplo, é subtrair os números e verificar se a casa decimal está suficientemente próxima de zero para se deduzir que os números são iguais.

As diferenças entre o Clipper e o XHarbour, nas multiplicações que você mostrou, talvez sejam devido à diferença de implementação das bibliotecas (principalmente rotinas de conversão). No Clipper foi utilizada a biblioteca C da Microsoft que, aliás, a princípio era também o emulador de ponto flutuante, já que àquela época não havia co-processador matemático nos chips (era um chip à parte). No XHarbour não sei, mas ao que parece, está melhor. Mas note que se você, no Clipper, usar Int(Round(x,2)), fica tudo certo também. Talvez o XHarbour já tenha isso automático. :)

Enviado: 30 Jan 2008 16:29
por asimoes
Maligno,

Como você bem disse, o ideal é usar nestes casos as funções round() ou str() até que se corrija, ou evitar tais comparações.

[]´s

Enviado: 30 Jan 2008 16:54
por Maligno
Corrijir? Não conte com correção. Até porque, não se pode dizer que alguém esteja errado. É só diferença de implementação.

Por enquanto eu continuo com minha conversão para strings:

Código: Selecionar todos

function CompNum(v1,v2,nDec)
default nDec to 2
return  Str(v1*(10**nDec),18) == Str(v2*(10**nDec),18)
Tem me resolvido esse tipo de problema muito bem.