Pontencia com alto expoente

Boa tarde amigos, estou precisando elevar 1.1 a potencia 60, mas com o math.pow nao esta dando o valor correto.

Estou fazendo uma aplicaçao financeira (juros compostos) quando o expoente é pequeno da tudo ok, mas quamdo o parcelamento e alto (60 vezes) a formula nao funciona como deveria.

Vf=vp*(1+i)^n

Onde i e a taxa, vp e capital, n e o tempo

Alguem pode me dar uma ajuda?

Para valores monetários, nunca utilize double. Utilize BigDecimal http://docs.oracle.com/javase/6/docs/api/java/math/BigDecimal.html#pow%28int%29.

quanto dá 1.1 na potencia 60.
e quanto o computador mostrou?

não sei porque com o math.pow, daria errado?
descobriu?

[quote=raghy]quanto dá 1.1 na potencia 60.
e quanto o computador mostrou?

não sei porque com o math.pow, daria errado?
descobriu?[/quote]

Os números de tipo float e double são armazenados como Mantissa + Expoente.

Por exemplo, o número 1 Milhão, duzentos e trinta e quatro mil poderia ser armazenado como algo assim:

1,234 x 10^6 : 1234-06 só utilizando 6 dígitos.

Com isso consigo representar números muito grandes ou muito pequenos em um espaço de memória pequeno. Por exemplo, só com 6 dígitos consigo representar o número 1 quaquilhão: 1000-99. 1,000 x 10^99.

Porém isto gera dois problemas:

  1. Há um limite máximo para o expoente a utilizar: Não consigo representar 10^100 na minha notação de exemplo, porque com dois dígitos só consigo chegar a 99.

  2. Não consigo representar um número com mais de quatro dígitos de precisão. O número 1 milhao, quinhentos e quarenta e oito mil, duzentos e trinta e oito, por exemplo, não poderia ser representado com meu exemplo.

Por isso, o java tem o BigDecimal: ele consegue armazenar números muito grandes, porque ele faz como nós: se falta dígitos na precisão, ele põe mais.

A classe BigDecimal tem um método pow, mas o método abaixo é mais “potente”, mas acredito que o método pow de BigDecimal já resolva seu problema.

[code]import java.math.BigDecimal;
import java.math.BigInteger;

/**
*

  • @author David Buzatto
    */
    public class Teste {

    /**

    • @param args the command line arguments
      */
      public static void main(String[] args) {

      BigDecimal v = arbitraryPow( new BigDecimal( “1.1” ), new BigInteger( “60” ) );
      System.out.println( v );

    }

    public static BigDecimal arbitraryPow( BigDecimal base, BigInteger exp ) {

     BigDecimal v = BigDecimal.ONE;
     
     while ( exp.compareTo( BigInteger.ZERO ) > 0 ) {
         v = v.multiply( base );
         exp = exp.subtract( BigInteger.ONE );
     }
     
     return v;
    

    }

}[/code]

Cara, discordo de que o método que você passou seja mais “potente”. Por que um método que simplesmente multiplica 60 vezes o número é mais “potente” que o método nativo da api, que usa algoritmos muito mais eficientes, criados por doutores em ciência da computação? Isto é a mesma coisa que tentar fazer a soma de 1 a 100 somando 1 + 2 + 3 + 4 + 5…

A todos coloco a seguinte recomendação: use sempre que possível bibliotecas nativas à API ou já prontas de uso amplamente adotado, não tentem reinventar a roda. Porque você vai acabar gerando métodos menos eficientes e gerando fontes extras de erros de lógica dentro do seu programa.

A missão dos cientistas da computação é ficar pensando como fazer uma tarefa computacional ser calculada de forma mais precisa e eficiente…

[quote=davidbuzatto]A classe BigDecimal tem um método pow, mas o método abaixo é mais “potente”, mas acredito que o método pow de BigDecimal já resolva seu problema.

[code]import java.math.BigDecimal;
import java.math.BigInteger;

/**
*

  • @author David Buzatto
    */
    public class Teste {

    /**

    • @param args the command line arguments
      */
      public static void main(String[] args) {

      BigDecimal v = arbitraryPow( new BigDecimal( “1.1” ), new BigInteger( “60” ) );
      System.out.println( v );

    }

    public static BigDecimal arbitraryPow( BigDecimal base, BigInteger exp ) {

     BigDecimal v = BigDecimal.ONE;
     
     while ( exp.compareTo( BigInteger.ZERO ) > 0 ) {
         v = v.multiply( base );
         exp = exp.subtract( BigInteger.ONE );
     }
     
     return v;
    

    }

}[/code][/quote]

1.1 elevado a 60 na calculadora do Windows é 304.48163954141809957444929536028
1.1 usando o Java é 304.48163954141955 (veja que só o último dígito está “errado”)

class TesteCalc {
    public static void main (String[] args) {
	    double d = Math.pow (1.1, 60);
		System.out.println (d);
	}
}

Para fazer esses cálculos de matemática financeira não é preciso fazer nenhuma mágica. Se você estivesse, no entanto, fazer algo como:
1.01 elevado a 720 (ou seja, juros de 1% ao mês durante 60 anos), dá um pouco mais de diferença (1292.3767115891916180624881537288 na calculadora do Windows, 1292.3767115891999 pelo Java).

E, notem: Tanto o valor do windows quanto o valor do java usando double estão “errados”. A calculadora do windows também usa números de ponto flutuante e, portanto, não são confiáveis para cálculos com números muito grandes, demandando muita precisão.

Usando o seguinte código java:

		BigDecimal d1 = new BigDecimal("1.1");
		System.out.println(d1.pow(60));

gera o número

304.481639541418099574449295360278774639038415066698088621947601

[quote=entanglement]1.1 elevado a 60 na calculadora do Windows é 304.48163954141809957444929536028
1.1 usando o Java é 304.48163954141955 (veja que só o último dígito está “errado”)

class TesteCalc {
    public static void main (String[] args) {
	    double d = Math.pow (1.1, 60);
		System.out.println (d);
	}
}

Para fazer esses cálculos de matemática financeira não é preciso fazer nenhuma mágica. Se você estivesse, no entanto, fazer algo como:
1.01 elevado a 720 (ou seja, juros de 1% ao mês durante 60 anos), dá um pouco mais de diferença (1292.3767115891916180624881537288 na calculadora do Windows, 1292.3767115891999 pelo Java). [/quote]

Bom, eu mesmo estou estudando matemática financeira, e normalmente não é necessário nada mais preciso que os cálculos feitos numa planilha do Excel (que usa o mesmo ponto flutuante (double) que o Java, para fazer os cálculos).

A única coisa que o Excel faz melhor é que ele não mostra tantos dígitos significativos - o Java mostra muitos dígitos e isso confunde muito as pessoas, que acham que as contas que o Java faz estão erradas.