Problema com subtração usando BigDecimal

4 respostas
A

Eu estou fazendo uma operação onde valor desejado = 1
e pValorObtido = 0.9999999999991193

E o resultado que estou tendo na operação:

diferencaDesejadosObtidos = diferencaDesejadosObtidos.subtract(valorObtido).setScale(MLP2.PRECISAO_VALORES,RoundingMode.HALF_UP);
é:
8.8073993E-13

O método por completo.
Ja fiz usando setScale nos dois bigdecimal, só que não resolve.
Alguem ja teve algum problema parecido?

private double calculaErro(double valorDesejado, double pValorObtido){
		
		BigDecimal diferencaDesejadosObtidos = new BigDecimal(valorDesejado);
	
		BigDecimal valorObtido = new BigDecimal(pValorObtido);

		diferencaDesejadosObtidos = diferencaDesejadosObtidos.subtract(valorObtido).setScale(MLP2.PRECISAO_VALORES,RoundingMode.HALF_UP);
		
		//quadradoValorObtido = valorObtido ^ 2
		BigDecimal quadradoValorObtido = new BigDecimal(pValorObtido).pow(2).setScale(MLP2.PRECISAO_VALORES,RoundingMode.HALF_UP);
		
		//valor = 1- valorObtido ^ 2
		BigDecimal valor = new BigDecimal(1).setScale(MLP2.PRECISAO_VALORES,RoundingMode.HALF_UP);
		valor = valor.subtract(quadradoValorObtido);
		valor = valor.setScale(MLP2.PRECISAO_VALORES,RoundingMode.HALF_UP);	
		//diferencaDesejadosObtidos * valor
		BigDecimal erro = diferencaDesejadosObtidos.multiply(valor).setScale(MLP2.PRECISAO_VALORES,RoundingMode.HALF_UP);
		
		return erro.doubleValue();
	}

4 Respostas

A

Sendo que ja fiz essa operação usando tipos primitivos e continuo com o mesmo problema.
Eu vi um post onde o Luca falava que era limite de maquinas computacionais, mas a calculadora do windows tambem não utiliza a mesma arquitetura para fazer o calculo?Porque o Java não faz o mesmo?

T

Dica: experimente subtrair os dois números

new BigDecimal (“1”)

e

new BigDecimal (“0.9999999999991193”)

(olhe as aspas). Qual será o resultado?

A
private double calculaErro(String valorDesejado,String pValorObtido){   
	       
	    BigDecimal diferencaDesejadosObtidos = new BigDecimal(valorDesejado);   
	  
	    BigDecimal valorObtido = new BigDecimal(pValorObtido);   
	  
	    diferencaDesejadosObtidos = diferencaDesejadosObtidos.subtract(valorObtido).setScale(MLP.PRECISAO_VALORES,RoundingMode.HALF_UP);   
	       
	    //quadradoValorObtido = valorObtido ^ 2   
	    BigDecimal quadradoValorObtido = new BigDecimal(pValorObtido).pow(2).setScale(MLP.PRECISAO_VALORES,RoundingMode.HALF_UP);   
	       
	    //valor = 1- valorObtido ^ 2   
	    BigDecimal valor = new BigDecimal(1).setScale(MLP.PRECISAO_VALORES,RoundingMode.HALF_UP);   
	    valor = valor.subtract(quadradoValorObtido);   
	    valor = valor.setScale(MLP.PRECISAO_VALORES,RoundingMode.HALF_UP);   
	    //diferencaDesejadosObtidos * valor   
	    BigDecimal erro = diferencaDesejadosObtidos.multiply(valor).setScale(MLP.PRECISAO_VALORES,RoundingMode.HALF_UP);   
	       
	    return erro.doubleValue();   
	}
Mudando para string, obtive o seguinte resultado,thingol:
diferencaDesejadosObtidos	5.9819250E-10
L

Olá

Todas as linguagens e ferramentas usam as mesmas coisas para fazer contas, isto é, usam as instruções de máquina que a CPU fornece. Algumas ferramentas ou linguagens pode apresentar resultados diferentes por fazer arredondamento automático (caso do antigo Clipper e pode ser o caso da calculadora do Windows).

Aqui mesmo no GUJ já escrevi diversas vezes como devemos fazer os cálculos com números de pontos flutuantes para manter o erro sob controle. Ninguém compara números de pontos flutuantes a menos da diferença de um número muito pequeno.

eps = 1.0e-9
real1 = 2.3
real2 = 4.7
if (abs(real1-real2) < eps)
print("real1 = real2")

[]s
Luca

Criado 1 de dezembro de 2007
Ultima resposta 3 de dez. de 2007
Respostas 4
Participantes 3