ZERO que não é ZERO
Moderador: Moderadores
ZERO que não é ZERO
(esta vai pro Maligno...)
Uma vez eu apanhei com uma comparação, onde o resultado de uma operação (a+b+c+d), que dava ZERO (no papel), resultava em .F. quando eu comparava com o número 0. Não lembro direito do detalhe, mas era algo do tipo:
a:=b:=10
c:=d:=-10
(a+b+c+d)=0 -> .F.
E isto porque (a+b+c+d) resultava em "0,000000000000001"...
Bão, eu dei uma pesquisada na época, achei algumas explicações, mas como elas eram 'muito' pro meu conhecimento de informática, abandonei a idéia de entender. E passei a usar algo que resolvia:
strzero(a+b+c+d,15,2)=strzero(0,15,2)
Nem sei porque lembrei disso agora, mas acho que é importante. Aliás, nem sei se soube iniciar a discussão! Alguém ae melhora a questão!
Uma vez eu apanhei com uma comparação, onde o resultado de uma operação (a+b+c+d), que dava ZERO (no papel), resultava em .F. quando eu comparava com o número 0. Não lembro direito do detalhe, mas era algo do tipo:
a:=b:=10
c:=d:=-10
(a+b+c+d)=0 -> .F.
E isto porque (a+b+c+d) resultava em "0,000000000000001"...
Bão, eu dei uma pesquisada na época, achei algumas explicações, mas como elas eram 'muito' pro meu conhecimento de informática, abandonei a idéia de entender. E passei a usar algo que resolvia:
strzero(a+b+c+d,15,2)=strzero(0,15,2)
Nem sei porque lembrei disso agora, mas acho que é importante. Aliás, nem sei se soube iniciar a discussão! Alguém ae melhora a questão!
-
Stanis Luksys
- Colaborador

- Mensagens: 1329
- Registrado em: 18 Jun 2005 03:04
- Localização: São Paulo
- Contato:
Opa,
Isso acontece pela forma como o compilador trabalha com os números, e no caso de grandes mantissas é uma limitação até mesmo da própria da máquina.
No caso do Clipper, e do exemplo acima que é um número razoavelmente simples, um SET DECIMALS deve resolver.
Isso é estudado em teoria dos erros, que explica, no campo do cálculo numérico, como é feito o arredondamento em máquinas, através da aritmética do ponto flutuante.
Isso acontece pela forma como o compilador trabalha com os números, e no caso de grandes mantissas é uma limitação até mesmo da própria da máquina.
No caso do Clipper, e do exemplo acima que é um número razoavelmente simples, um SET DECIMALS deve resolver.
Isso é estudado em teoria dos erros, que explica, no campo do cálculo numérico, como é feito o arredondamento em máquinas, através da aritmética do ponto flutuante.
Stanis Luksys
sites.google.com/hblibs
Apoiar e se utilizar de projetos opensource não é uma questão de boicote, mas sim de liberdade.
Utilize, aprimore e distribua.
sites.google.com/hblibs
Apoiar e se utilizar de projetos opensource não é uma questão de boicote, mas sim de liberdade.
Utilize, aprimore e distribua.
-
Stanis Luksys
- Colaborador

- Mensagens: 1329
- Registrado em: 18 Jun 2005 03:04
- Localização: São Paulo
- Contato:
Opa,
Existe sim uma explicação matemática, e é exatamente a partir do tema que eu já citei: teoria dos erros.
No estudo dessa parte do cálculo numérico verificamos quais são as possibilidades de arredondamento de um número segundo as regras estabalecidas pela capacidade da máquina (ou do soft no caso). Um exemplo claro disso é a calculadora comum, que possui apenas 8 dígitos.
O arredondamento no computador independe de ser realizada alguma operação artimética, ele sempre é executado quando se trata de pontos flutuantes. Existe uma fórmula que define o modo como é realizado o arrendodamento, e é bem grandinha...
Por exemplo, o número 5 em ponto flutuante é:
0,5000000... x10^1
Sendo que haverá depois da vírgula quantas casas a máquina "suportar", no caso dos computadores, tanto a máquina como o software influenciam. Este número de casas após a vírgula (o tamanho da mantissa, como eu disse la no outro post) também é uma das variáveis da tal fórmula...
Etc e tal....
Sei que num deu pra entender nada do que falei, mas enfim, é por aí caminho pra entender este erro, mais evidente no Clipper por não permitir a declaração direta de números float.
Falou!
Existe sim uma explicação matemática, e é exatamente a partir do tema que eu já citei: teoria dos erros.
No estudo dessa parte do cálculo numérico verificamos quais são as possibilidades de arredondamento de um número segundo as regras estabalecidas pela capacidade da máquina (ou do soft no caso). Um exemplo claro disso é a calculadora comum, que possui apenas 8 dígitos.
O arredondamento no computador independe de ser realizada alguma operação artimética, ele sempre é executado quando se trata de pontos flutuantes. Existe uma fórmula que define o modo como é realizado o arrendodamento, e é bem grandinha...
Por exemplo, o número 5 em ponto flutuante é:
0,5000000... x10^1
Sendo que haverá depois da vírgula quantas casas a máquina "suportar", no caso dos computadores, tanto a máquina como o software influenciam. Este número de casas após a vírgula (o tamanho da mantissa, como eu disse la no outro post) também é uma das variáveis da tal fórmula...
Etc e tal....
Sei que num deu pra entender nada do que falei, mas enfim, é por aí caminho pra entender este erro, mais evidente no Clipper por não permitir a declaração direta de números float.
Falou!
Stanis Luksys
sites.google.com/hblibs
Apoiar e se utilizar de projetos opensource não é uma questão de boicote, mas sim de liberdade.
Utilize, aprimore e distribua.
sites.google.com/hblibs
Apoiar e se utilizar de projetos opensource não é uma questão de boicote, mas sim de liberdade.
Utilize, aprimore e distribua.
Re: ZERO que não é ZERO
Na aritmética de inteiros, que são sempre maioria no computador, comparações desse tipo podem ser feitas sempre sem qualquer preocupação. O problema é que no Clipper, por não ser a XBase uma linguagem tipada, todos os números são em ponto flutuante. E nesse tipo de dado, zero nunca é zero. A solução é exatamente essa que você propôs: converter para string e comparar. A teoria disso é realmente bem complexa. Mas se você quiser um tutorial a respeito (é bem interessante), clique aqui.Eolo escreveu:Uma vez eu apanhei com uma comparação, onde o resultado de uma operação (a+b+c+d), que dava ZERO (no papel), resultava em .F. quando eu comparava com o número 0.
Inclusive, em algumas linguagens tipadas, uma solução é simplesmente inferir: "se for menor que 0,0000001, considere como sendo igual zero". O quê, aliás, também pode ser feito no Clipper. Mas eu prefiro converter pra string.
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.
---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.
---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
-
Stanis Luksys
- Colaborador

- Mensagens: 1329
- Registrado em: 18 Jun 2005 03:04
- Localização: São Paulo
- Contato:
Complementando,
Números em ponto flutantes obrigatoramente sempre tem o formato:
0,abcde . x ^ y
Onde a deve ser semprwe diferente de zero.
Por isso o menor número representado em ponto flutante é sempre 0,1 elevado a menor potência possível dentro das capacidades da máquina.
Exemplo:
0,100000 x 10 ^ (- 9999999999999999999999999999999999999)
Um número bem pequeno, mas nunca igual a zero....
Números em ponto flutantes obrigatoramente sempre tem o formato:
0,abcde . x ^ y
Onde a deve ser semprwe diferente de zero.
Por isso o menor número representado em ponto flutante é sempre 0,1 elevado a menor potência possível dentro das capacidades da máquina.
Exemplo:
0,100000 x 10 ^ (- 9999999999999999999999999999999999999)
Um número bem pequeno, mas nunca igual a zero....
Stanis Luksys
sites.google.com/hblibs
Apoiar e se utilizar de projetos opensource não é uma questão de boicote, mas sim de liberdade.
Utilize, aprimore e distribua.
sites.google.com/hblibs
Apoiar e se utilizar de projetos opensource não é uma questão de boicote, mas sim de liberdade.
Utilize, aprimore e distribua.
Me lembrei agora dos tempos do bom e velho 8088, que não tinha núcleo de ponto flutuante e dependia do uso de um emulador (ainda presente no Clipper) ou de um co-processador, o 8087. Só tive um cliente que comprou. Era caro paca. 
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.
---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.
---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Já tive um problema semelhante na divisão de 9,60 por 3 que ele teimava em dizer que cada parcela não era 3,20. Quando somado as tres parcelas e comparado ao valor inicial (9,60) nao batia.
Um colega postou uma função que ainda uso. Resolveu.
O Maligno à época também postou a função abaixo:
Jânio
Um colega postou uma função que ainda uso. Resolveu.
Código: Selecionar todos
*** PROCEDURE para Comparar duas variaveis numericas ***
FUNCTION Compara(nValor1,nValor2) && COMPARA VALORES REAIS ...
IF VAL(STR(nValor1)) == VAL(STR(nValor2))
RETURN(.T.) && OK ...
ELSE
RETURN(.F.) && PROBLEMAS ...
END
***
Código: Selecionar todos
function CompNum(v1,v2,nDec)
default nDec to 2
return Str(v1*(10**nDec),18) == Str(v2*(10**nDec),18)
Editado pela última vez por janio em 05 Set 2007 08:28, em um total de 1 vez.
fui...
e-mail:janioaguiar@yahoo.com.br
msn: janio_aguiar@hotmail.com
xHarbour1.2.1/Harbour3.2 + wvg + hwgui + Mediator + MySql
e-mail:janioaguiar@yahoo.com.br
msn: janio_aguiar@hotmail.com
xHarbour1.2.1/Harbour3.2 + wvg + hwgui + Mediator + MySql
É essa mesma que eu uso. Prefiro ela, que é mais genérica (nDec mutável). Mas a função anterior resolve bem com valores monetários, já que os dois Val() reconvertem os valores que são arredondados igualmente pelas chamadas às Str(). Aí a comparação se torna precisa.function CompNum(v1,v2,nDec)
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.
---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.
---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
O bom é que, uma vez programando em alto nível, não é necessário se preocupar com esses detalhes. Isso só aparece mais em um nível mais baixo. Mas ainda assim, é uma coisa interessante. 
[]'s
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.
---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!
Maligno
---
Não respondo questões técnicas através de MP ou eMail. Não insista.
As dúvidas devem ser postadas no fórum. Desta forma, todos poderão
se beneficiar das respostas.
---
Se um dia precisar de uma transfusão de sangue você perceberá como
é importante a figura do doador. Procure o hemocentro de sua cidade e
se informe sobre a doação de sangue, plaquetas e medula óssea. Doe!


