Um "grande" problema

Pessoal,
Atualmente estou cursando o primeiro período de Tecnologia da Informação e claro, estou estudando também a lógica de programação. Para ir “adiantando” as coisas, já que eu vou ter lógica no primeiro, segundo, terceiro e quarto período, resolvi por conta própria fazer um curso avançado de lógica em um outro lugar privado. Bom, esse outro curso terminou e resolvi entrar em um curso de JAVA privado também para ir adiantando mais ainda as coisas para mim. E então, na aula de hoje de lógica (na faculdade) a professora passou um exercício matemático muito antigo, mas muito mesmo, que eu de certa forma consegui resolver, mas infelizmente está acontecendo uma coisa que eu não estou conseguindo entender, e vou explicar a vocês.

Primeiro, vou expor o exercício.

    [b]Uma rainha requisitou os serviços de um monge e disse-lhe que pagaria qualquer preço para que o serviço fosse realizado. O monge, necessitando de alimentos, perguntou à rainha sobre o pagamento, se poderia ser feito com grãos de trigo dispostos em um tabuleiro de xadrez, de tal forma que o primeiro quadro deveria conter apenas um grão e os quadros subsequentes, o dobro do quadro anterior. A rainha achou o trabalho barato e pediu que o serviço fosse executado, sem se dar conta de que seria impossível efetuar o pagamento. Faça um algoritmo para calcular o número de grãos que o monge esperava receber.[/b]

Segundo, agora vamos a lógica do problema.

    Bom, se um tabuleiro de xadrez tem exatamente 64 posições e na primeira delas tem 1(2^0) grão, então na segunda terá (2^1) grãos, e isso é percorrido até a última posição(64), irá conter 2^63 grãos, então o resultado final seria em teoria somente eu criar uma variável que guardasse a soma dos grãos de todas as posições, certo? 

Beleza…beleza… então vamos agora para a minha lógica feita no VisualG…

algoritmo "A Rainha e o Monge" var soma : real contador : inteiro inicio para contador de 0 ate 63 faca soma <- soma + 2^contador fimpara escreva("O total de grãos é: ", soma) fimalgoritmo

A saída no VisualG foi “O total de grãos é: 1.84467440737096E19”

Fiquei muito insatisfeito com o certo “E” ali no antepenúltimo dígito e pensei… será que isso é porque o VisualG não consegue trabalhar com números muito grandes, como o caso do meu problema? E logo depois pensei, porque não tentar fazer em JAVA e ver na realidade mesmo o número bruto, o JAVA deve suportar números extremamente grandes…

Então tá, lá vou eu com apenas 2 aulas de JAVA tentar fazer algum “FAIL code” no Eclipse…

Fui tentar traduzir a minha lógica exatamente como tinha feito no VisualG e fiz o seguinte código:

[code]public class RainhaMonge {

public static void main(String[] args) {

	double soma = 0;

	for (int i = 0; i <= 63; i++) {

		soma = soma + Math.pow(2, i);

	}

}

}[/code]

Todo feliz por ter conseguido usar os comandos sem dar nenhum erro no Eclipse apertei Ctrl+F11 e a saída foi…

18446744073709552E19

Putz… fiquei muito grilado por ver o INFERNO de E novamente em meu número e resolvi ir no Google procurar o resultado REAL do problema em questão e encontrei o seguinte resultado no Yahoo! Grupos.

18446744073709551615

Comparando os dois resultados, são bem parecidos sim… mas o meu está arredondado, ou sei la o que significa esse tal E aí… então resolvi perguntar a um amigo meu como faria para resolver tal problema e então ele me sugeriu o seguinte código…

[code]import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.Locale;

public class RainhaMonge {

public static void main(String[] args) {

	double soma = 0;

	for (int i = 0; i <= 63; i++) {

		soma = soma + Math.pow(2, i);

	}

	BigDecimal numero = BigDecimal.valueOf(soma);
	NumberFormat nf = NumberFormat
			.getNumberInstance(new Locale("pt", "BR"));
	System.out.println(nf.format(numero));
}

}[/code]

Executando o mesmo… a saída é 18.446.744.073.709.552.000
Ainda sim está diferente do encontrado no Yahoo! Grupos… que era 18.446.744.073.709.551.615

Comparação:

          MEU:     18.446.744.073.709.552.000
          Yahoo:  18.446.744.073.709.551.615

Dá pra ver que o JAVA arredondou o meu número… e eu não fiquei nem um pouco satisfeito com isso, quero o número REAL, não quero um arredondamento…
Por favor, me ajudem a pensar sobre o que está ocorrendo? Eu não estou conseguindo entender o motivo do arredondamento… O que eu faço?

Usa BigDecimal nas contas:

import java.math.BigDecimal;  
      
public class RainhaMonge {  
      
    public static void main(String[] args) {  
        BigDecimal DOIS = new BigDecimal(2);
        BigDecimal soma = BigDecimal.ZERO;  
      
        for (int i = 0; i <= 63; i++) {  
      
            soma = soma.add(DOIS.pow(i));  
      
        }  
      
        System.out.println(soma);  
           
    }  
      
}  

Ou, numa única linha, sem precisar do ciclo for:

import java.math.BigDecimal;  

public class RainhaMonge {  
      
    public static void main(String[] args) {  
      
        System.out.println(new BigDecimal(2).pow(64).subtract(BigDecimal.ONE));  
           
    }  
      
}  

plml,

Muito obrigado mesmo pela sua resposta, ela foi muito clara pra mim e fez exatamente o que eu queria, um código enxuto e funcional, essa minha dúvida foi postada também no fórum de discussão do orkut e também obtive algumas respostas legais, mas não tão pequenas quanto a sua! Irei postar abaixo as respostas que obtive apenas a nível de curiosidade mesmo, se puder dar uma analisada depois seria legal! Aproveitando, estou pensando em comprar aquele livro “Use a cabeça JAVA”, é bom? é ruim? Tem melhor para iniciantes? Obrigado mesmo plml! E espero mais respostas suas e do pessoal por aí! Valeu!

Código do usuário DEH:

[code]BigDecimal soma = new BigDecimal(0);

for (int i = 0; i <= 63; i++) {

soma = soma.add(new BigDecimal(Math.pow(2, i)));

}

System.out.println(soma);[/code]