BigDecimal, problemas com precisão

8 respostas
T

Pessoal, preciso fazer um programa para minha aula de cálculo numérico da faculdade.

Preciso usar o metodo da Interação Linear para calcular as raizes de uma equação.

Esse metodo precisa de muita precisão, na casa de 7 digitos depois da virgula. Pelo que percebi nem float nem double tem essa precisão, ate 1564/5 nesses formatos me retorna um valor errado.

Olha o programa que tentei fazer:

package Questão4;

import java.math.BigDecimal;

public class InteracaoLinear4 {
	
	public static void main(String args[]) {
		
		BigDecimal teste2 = new BigDecimal(2.000);
		BigDecimal teste3 = new BigDecimal(87);
		BigDecimal teste = new BigDecimal((double)1564/5);
		
		BigDecimal teste4 = new BigDecimal(200);

		teste4 = teste4.multiply(teste2);
		teste4 = teste4.add(teste3);
		teste = teste.multiply(teste2);
		teste = teste.add(teste3);
		
		
		BigDecimal another2 = teste4.setScale(7, teste4.ROUND_HALF_DOWN);
		BigDecimal another = teste.setScale(7, teste.ROUND_HALF_DOWN);
		
                another = another.divide(another2);
		
		
		System.out.println(another);

	  }

}

Qdo. faço a ultima divisão, "another = another.divide(another2);" o programa retorna esse erro:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(Unknown Source)
at Questão4.InteracaoLinear4.main(InteracaoLinear4.java:24)

Alguem sabe o que é isso e como eu posso arrumar? O valor another e another2, por si só, estão corretos e com a precisão que eu desejo. O problema é na divisão.

Obrigado desde já!

8 Respostas

P
BigDecimal teste = new BigDecimal((double)1564/5);

Eu não entendi muito bem essa linha. Você gostaria de obter um valor mais exato de 1564/5 ou não? Caso afirmativo, você deveria fazer a divisão entre um BigDecimal 1564 e outro BigDecimal 5 invés de fazer um cast para double e então criar um BigDecimal, não?

T

Valeu pela dica. Vou tentar.

Fiz isso pq só BigDecimal teste = new BigDecimal(1564/5); não me retorna o valor correto.

Sem o cast o prog. retorna 312 apena, e não 312,8.

RDSILVA

Fala ai camarada…
cara acho que mais ou menos isso que vc quer fazer da uma olhada ai, peguei sua classe e alterei umas coisas
qq coisa da um toque

import java.math.BigDecimal;

public class TesteBigDecimal {
	
	public static void main(String[] args) {
	
		BigDecimal teste1 = new BigDecimal((double)1564/5);
		BigDecimal teste2 = new BigDecimal(2.000);   
        BigDecimal teste3 = new BigDecimal(87);   
        BigDecimal teste4 = new BigDecimal(200);   
          
        System.out.println("teste1 = " + teste1);
        System.out.println("teste2 = " + teste2);
        System.out.println("teste3 = " + teste3);
        System.out.println("teste4 = " + teste4);
        
        teste4 = teste4.multiply(teste2);
        
        System.out.println("teste4 = " + teste4);
        
        teste4 = teste4.add(teste3);
        
        System.out.println("teste4 = " + teste4);
        
        teste1 = teste1.multiply(teste2);
        
        System.out.println("teste1 = " + teste1);
        
        teste1 = teste1.add(teste3);
        
        System.out.println("teste1 = " + teste1);
        
        BigDecimal teste5 = teste4.setScale(7,teste4.ROUND_HALF_DOWN);
        
        System.out.println("teste5 = " + teste5);
        
        BigDecimal teste6 = teste1.setScale(7,teste1.ROUND_HALF_DOWN);
        
        System.out.println("teste6 = " + teste6);
        
        teste6 = teste6.divide(teste5, teste6.ROUND_HALF_DOWN);
        
        System.out.println("teste6 = " + teste6);
        
	}
	
	
}
T

Grande RDSILVA!

Isso mesmo, deu certinho. Valeu pela ajuda.

Mas tem outra, eu agora preciso do ln (logaritmo na base de euller) do numero armazenado no teste6.

Existe alguma forma de fazer isso? Eu tentei o Math.log(), mas ele não aceita BigDecimal como argumento. O BigDecimal não acieta casting para float ou Double.

Como posso fazer isso?

T

Massa! Acho que consegui.

Fiz assim:

float x;
         x = teste6.floatValue();
         
         System.out.println("x = " + x);
         
         System.out.println("Log(x) = " + Math.log(x));

Saiu o valor com a precisão que eu desejo.

Valeu demais pela ajuda!

T

RDSILVA, que que você fez de diferente pra sua divisão dar certo?

E, você sabe de algum método de calcular ln melhor que esse que eu encontrei. Dicas são sempre bem vindas.

zinho

Tours.
O RDSILVA matou a charada mas você entendeu o que estava errado, como ele resolveu o porque?
Caso a resposta seja não, dê uma lida no javadoc do BigDecimal que explica tudo:
http://java.sun.com/javase/6/docs/api/

zinho

Exemplificando o problema:

public class Teste {
	
	/**
	 * @param args
	 */
	public static void main(String args[]) {
		
		BigDecimal um = new BigDecimal(1);
		BigDecimal tres = new BigDecimal(3);
		
		BigDecimal dizima;
		
		try {
			dizima = um.divide(tres); // Dizima periódica - Exception
		}
		catch (ArithmeticException e) {
			dizima = um.divide(tres, BigDecimal.ROUND_HALF_DOWN);
		}
		
		System.out.println(dizima);

	}
}
Criado 23 de agosto de 2008
Ultima resposta 23 de ago. de 2008
Respostas 8
Participantes 4