Precisão Numérica Excel para Java  XML
Índice dos Fóruns » Java Avançado
Autor Mensagem
Ironlynx
Moderador
[Avatar]

Membro desde: 02/05/2003 01:06:41
Mensagens: 3515
Localização: The other side of the screen
Offline

Bom, estou fazendo uma app que subtitui uma planilha excel para cálculos.Basicamente eu pego dois números num dado período de tempo para calcular dois indicadores e depois pego cada indicador e multiplico por um peso(por exemplo 0.2 e 0. para obter o resultado de uma variação em % após subtrair um pelo outro.São 3 métodos:

Exemplo de entradas:
double resultado_do_primeiro_indicador=sr.calcularIndicador(360.6400,341.0100);
double resultado_do_segundo_indicador=sr.calcularIndicador(396.9720,345.7240);
Aí eu tenho a sequência:

E o final:
double resultado=sr.calcularResultado(parte1indicador,parte2indicador);
O que me dá:0.13016
Mas o correto deveria ser:
0.130106 que depois dará convertido: 13,0106% de variação.
Eu gostaria de saber se alguém sabe o "RANGE" ou o que governa a precisão do Excel para eu fazer o mesmo no java.

Não basta persistir...tem que prevalecer!
Ironlynx
Anarquista de Sistemas
http://osereojava.blogspot.com/
[WWW]
Focão
JavaTeenager
[Avatar]

Membro desde: 09/03/2005 09:49:33
Mensagens: 182
Offline

vc não pode usar double..

pq Double.MAX_VALUE = 1.7976931348623157E308

altere a assinatura public double

para

public BigDecimal




public static void main(Object... thisCompile) {
for (Object JavaIsCool : thisCompile);
}
Ironlynx
Moderador
[Avatar]

Membro desde: 02/05/2003 01:06:41
Mensagens: 3515
Localização: The other side of the screen
Offline

Focão, não preciso de precisão numérica, pois double vai até algo entre 15 ou 17 casas decimais.O que eu preciso é de EXATIDÂO.
Eu mudei os métodos para receberem e entregarem Strings, mas meu resultado é: 0.130100 e eu deveria receber isso:
0.130106, entendeu?

Não basta persistir...tem que prevalecer!
Ironlynx
Anarquista de Sistemas
http://osereojava.blogspot.com/
[WWW]
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

Alguma coisa está errada.

Eu sei que o Excel trabalha internamente com double ou "long double" (80 bits), até porque ele usa as instruções do processador para acelerar o cálculo.
(Ele só arredonda para visualização, não para cálculo. Isso você pode confirmar fazendo uma planilha que contenha 2 valores muito próximos, que apareçam iguais se você formatar com poucas casas depois da vírgula, e criar uma célula que seja a diferença desses dois valores, mas formatado com muitas casas depois da vírgula. Você vai ver que a diferença é calculada de acordo com o valor real e não o mostrado pela formatação.)



Mas executando o programa acima (que é basicamente o seu, sem usar essa frescura de BigDecimal) deu o resultado:



Alguém está comendo bola nessa história.

This message was edited 1 time. Last update was at 28/01/2009 15:14:34

[WWW]
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

E de qualquer maneira, mesmo que o Excel use "long double" (80 bits) internamente, as operações que você fez não estão em um intervalo "instável" - ou seja, onde qualquer modificação infinitesimal nos valores dos parâmetros se reflita com valores muito grandes no resultado. As contas que você fez, na verdade, dão aproximadamente mesmo resultado mesmo com "float" (32 bits), que tem uma precisão muito ruim para fazer contas.
[WWW]
Ironlynx
Moderador
[Avatar]

Membro desde: 02/05/2003 01:06:41
Mensagens: 3515
Localização: The other side of the screen
Offline

Thingol, o programa que eu tô fazendo é para substituir um feito em planilha excel, lembrando que as entradas originais:

double resultado_do_primeiro_indicador=sr.calcularIndicador(360.6400,341.0100);
double resultado_do_segundo_indicador=sr.calcularIndicador(396.9720,345.7240);

São valores oriundos de uma planilha Excel(claro, lá estão com vírgulas ao invés de double). E o resultado final: 13,0106% de variação, vem da mesma.
O que eu tõ fazendo é tentar "bater" com ela, entendeu? Olha ela aqui(ver FM1):
http://img217.imageshack.us/my.php?image=imagemexcelsb7.jpg

Não basta persistir...tem que prevalecer!
Ironlynx
Anarquista de Sistemas
http://osereojava.blogspot.com/
[WWW]
gomesrod
GUJ Ranger
[Avatar]

Membro desde: 11/05/2007 19:46:22
Mensagens: 901
Online

Eu fiz um pequeno "tira-teima" aqui, com o seguinte trecho:

Seguindo os métodos de cálculo que você colocou, eu fiz na calculadora:


O que bateu com o resultado que vc obteve no programa em Java! E veja que não fiz nenhum arredondamento para não ter perigo de perda de precisão... Será que o problema não pode estar na planilha excel e não no seu programa?
Focão
JavaTeenager
[Avatar]

Membro desde: 09/03/2005 09:49:33
Mensagens: 182
Offline

cara tem q ser tudo BigDecimal

Já aconteceu comigo...

faz o teste aí....
o problema é precisão numérica do double mesmo

lembre-se precisão numérica = exatidão


se der dizima vc perde no excel


BigDecimal parte1indicador = sr.calcularIndicadorComPeso(1.0576, 0.2);
BigDecimal parte2indicador = sr.calcularIndicadorComPeso(1.1483, 0.;
BigDecimal resultado = sr.calcularResultado(parte1indicador, parte2indicador);

This message was edited 1 time. Last update was at 28/01/2009 16:34:16


public static void main(Object... thisCompile) {
for (Object JavaIsCool : thisCompile);
}
Focão
JavaTeenager
[Avatar]

Membro desde: 09/03/2005 09:49:33
Mensagens: 182
Offline

se liga como





olha o tamanho das crianças... hehehe

public static void main(Object... thisCompile) {
for (Object JavaIsCool : thisCompile);
}
Ironlynx
Moderador
[Avatar]

Membro desde: 02/05/2003 01:06:41
Mensagens: 3515
Localização: The other side of the screen
Offline

Precisão é o numero de digitos, exatidão é a proximidade do resultado verdadeiro.(Lembre-se que toda máquina esbarra uma hora numa limitação binária)
Focão, não use o double no construtorBigDecimal, dá resultados bizarros.Prefira passar Strings.Passando só Strings, eu obtenho a série:

Cálculo do indicador 1(MO):1.057565
Cálculo do indicador 2(PI):1.148234
Cálculo do indicador 1(MO) com peso:0.211513
Cálculo do indicador 2(PI) com peso:0.918587
Resultado em final:0.130100


Não basta persistir...tem que prevalecer!
Ironlynx
Anarquista de Sistemas
http://osereojava.blogspot.com/
[WWW]
Ironlynx
Moderador
[Avatar]

Membro desde: 02/05/2003 01:06:41
Mensagens: 3515
Localização: The other side of the screen
Offline

Thingol, esse trabalho que eu tô fazendo é para um engenheiro.Como você é engenheiro, eu pergunto para fins de exatidão, eu uso double(pode ser o simples como vc fz mesmo, sem usar BD),ou um BigDecimal passando Strings ao construtor?O primeiro dá o resultado que vc já conhece 0,130160 e o segundo 0.130100.Alguém tem uma HP12C aí?

Não basta persistir...tem que prevalecer!
Ironlynx
Anarquista de Sistemas
http://osereojava.blogspot.com/
[WWW]
Focão
JavaTeenager
[Avatar]

Membro desde: 09/03/2005 09:49:33
Mensagens: 182
Offline

Ironynx agora q não entendi o que vc quer de verdade..

Posso ter me expressado mal igualdade em Precisão = Exatidão

Na verdae pelo contexto está implicito que quiz dizer que quanto maior a precisão maior a exatidão por isso sugeri o BigDecimal

Agora passar String pra Cálculo não concordo... prefiro os resultado bizarros... como o que te passei olha a precisão:

parte1indicador 0.2115200000000000308553183003823516324714888418409564037749203053474789104626552216359414160251617431640625
parte2indicador 0.91864000000000012972289908930179517954823355080921057472625166663571238956365050398744642734527587890625
resultado 2.1301600000000001605782173896841468120197223926501669785011719719831913000263057256233878433704376220703125

Agora em conceito...

Precisão é o grau de variação das medidas que vc faz. Ou seja, se vc tirar 10 medidas com cada um de dois equipamentos diferentes, o que
apresentar menos medidas diferentes é o que tera maior precisão. Exatidão é quanto a medida se aproxima da realidade, ou seja, a parte que é constante no erro. Por exemplo, se vc tem uma diferença de 2 milimetros em uma regua, com relação ao valor exato, vc tera um erro sistematico de 2 militros em todas as medidas. Esse valor fornece a exatidão da regua

Agora em Dic Michaelis

e.xa.ti.dão
(z), s. f. 1. Caráter ou qualidade de exato. 2. Rigor na determinação de medida, peso, valor etc. 3. Atenção minuciosa no cálculo. 4. Cumprimento rigoroso, observância à risca de ajuste, contrato etc. 5. Verdade na exposição dos fatos.
pre.ci.são
s. f. 1. Falta ou insuficiência de algo necessário ou útil. 2. Urgência, necessidade. 3. Rigor sóbrio de linguagem. 4. Caráter do que é nítido, exato. 5. Justeza, regularidade material.

Agora nossa praia Java Doc

A classe BigDecimal dá o seu usuário o controle completo sobre arredondamento comportamento, forçando o usuário a especificar explicitamente um comportamento arredondamento para operações capaz de desfazer precisão

Lembrando que SUA PERGUNTA ERA:

Eu gostaria de saber se alguém sabe o "RANGE" do Excel ?

então a resposta é :

30 casas decimais..

quero ver isso em double.

BOA SORTE ! na sua implementação.


This message was edited 1 time. Last update was at 29/01/2009 08:47:18


public static void main(Object... thisCompile) {
for (Object JavaIsCool : thisCompile);
}
thingol
Moderador

Membro desde: 29/07/2004 16:10:13
Mensagens: 17543
Offline

Ironlynx wrote:Thingol, esse trabalho que eu tô fazendo é para um engenheiro.Como você é engenheiro, eu pergunto para fins de exatidão, eu uso double(pode ser o simples como vc fz mesmo, sem usar BD),ou um BigDecimal passando Strings ao construtor?O primeiro dá o resultado que vc já conhece 0,130160 e o segundo 0.130100.Alguém tem uma HP12C aí?


Hum... como acho que o Excel não esteja fazendo contas erradas, o que acho é que você está passando para sua rotina Java dados que você copiou da planilha Excel com apenas as 6 casas de precisão.

De qualquer maneira, em análise numérica há duas formas de proceder:

- Uma delas é calcular com o máximo de precisão possível (double ou long double) os cálculos intermediários e efetuar apenas na saída o arredondamento - isso é mais fácil, mas exige alguma análise para determinar se pequenos erros nos dados de entrada não causarão grandes erros na saída;

- A outra, que é mais complicada, é usar "interval arithmetic".
Ou seja, se você tem um dado que é 1.23 +/- 0.01 e vai somar com outro que é 34.56 +/- 0.1, você intuitivamente sabe que o resultado é (1.23 + 34.56) +/- (0.01 + 0.01), que é 35.79 +/- 0.02.
Se você tivesse o dado 35.79 +/- 0.01 e subtraísse de 34.56 +/- 0.01, o resultado é 1.23 +/- 0.02.
A multiplicação é um pouco mais complicada. Por exemplo, (1.23 +/- 0.01) * (34.56 +/- 0.01) dá (1.23 * 34.56) +/- (1.23 + 34.56) * 0.01 + 0.01 * 0.01) = 42.5088 +/- 0.3580. O resultado é surpreendente, já que você pensaria que 1.23 * 34.56 daria algo com 2 casas depois da vírgula (mais ou menos), mas na verdade nem dá a precisão de 1 casas depois da vírgula.
Para isso, use uma biblioteca que implementa "interval arithmetic", como a http://interval.sourceforge.net/interval/java/ia_math/README.html

Ou seja, você vê que à medida que você vai acumulando dados, as suas inexatidões vão se acumulando também.

EDIT - Hum... fiz uma conta errado. Mas a conclusão é a mesma.

This message was edited 1 time. Last update was at 29/01/2009 12:37:45



[WWW]
correainfo
JavaGuru
[Avatar]

Membro desde: 16/04/2005 21:04:25
Mensagens: 240
Localização: São Paulo SP - Cidade Natal : Auriflama,SP
Offline

Fiz um teste aqui e cheguei no seu resultado...
O problema que eu achei é no metodo calcularIndicador

Vc estava passando com quatro casas decimais assim



No teste que eu fiz passei com duas casas decimais e no calculo do peso estou arrendondo para baixo.


Segue o exemplo



Resultado: 0.130106


Espero ter ajudado..

This message was edited 1 time. Last update was at 29/01/2009 09:21:28


11-75333451

Desenvolvedor Java e IPhone



[Email] [MSN]
Ironlynx
Moderador
[Avatar]

Membro desde: 02/05/2003 01:06:41
Mensagens: 3515
Localização: The other side of the screen
Offline

thingol, ótimos toques.O cara deve ter vacilado em alguma coisa.Os dados das entradas foram salvos todos com 4 casas na base.Eu uso 6 para poder obter a % de cada indicador com 4 casas(logico que depois eu multiplico por 100).
correainfo, valeu pelo teste.Mas não sei se posso considerar tão valido pois há numeros assim 341.9113, que jamais poderiam ser desprezados, e o estranho é que eles estão usando maior que 5, arredonda para cima.

Não basta persistir...tem que prevalecer!
Ironlynx
Anarquista de Sistemas
http://osereojava.blogspot.com/
[WWW]
 
Índice dos Fóruns » Java Avançado
Ir para:   
Powered by JForum 2.1.8 © JForum Team