Pergunta de iniciante

Olá,

Neste exercicio básico que tansforma pés em metros surgiu-me a seguinte dúvida.

    // get input from user
    Scanner input = new Scanner(System.in);
    System.out.print("Enter a value for feet: ");
    double feet = input.nextDouble();

    // convert feet into meters
    double meters = feet * 0.305;

    // present the result
    System.out.println(feet + " feet is " + meters + " meters.");

Se o valor de entrada for 10 o resultado é 3.05. Tudo bem.
Alterando no código o “0.305” por “3.305” o resultado é 33.050000000000004. Porquê tantas casas decimais e o “4” no final?

Talvez porque seja o resultado, literalmente.
Números são infinitos. 33.0504 é completamente diferente de 33.050004 que é totalmente diferente de 33.050000000000004
Mas isso não quer dizer que não exista um 33.050000000000014 ou 33.050000000000000000000000004
O que tu pode fazer é formatar esse número pra só aparecer duas casas decimais, por exemplo.

Chaybelucas, obrigado pela ajuda. Eu sou inciante no java mas não na matematica. Acho que 10*3.305 dá 33.05 sem arredondamentos e não 33.050000000000004. Ainda pensei que fosse algum bug do netbeans , mas experimentei no bluej e dá igual. Ou seja existe alguma coisa no java que me está a escapar.
O código da minha primeira mensagem talvez esteja a confundir. Alterei o codigo de forma a mostrar o problema. Introduzindo o valor 10, ou seja pedindo ao programa que multiplique 10 por 3.305. Porquê que ele retorna um valor errado?

// Introduzir um valor
Scanner input = new Scanner(System.in);
System.out.print("Introduza um valor: ");
double valor = input.nextDouble();

// Multiplicar por 3.305
double resultado = valor * 3.305;

// Apresentar o resultado
System.out.println("O resultado é  " + resultado);

Você provavelmente está se deparando com uma limitação na forma como os números de ponto flutuante (float, double) são representados em binário. Esse é um problema antigo e conhecido da ciência da computação como um todo (não só Java). Dependendo do número representado, podem haver pequenas diferenças nos cálculos, porque a representação em binário não é precisa (um exemplo clássico é o 0.1).

Suas opções são tentar arredondar ou truncar o número calculado para menos casas decimais.

Abraço.

1 curtida

Você pode resolver usando BigDecimal:

	double resultado = 10 * 3.305;
	System.out.println(resultado); //mostra "33.050000000000004"
	
	BigDecimal b1 = new BigDecimal("10"); //Passe String para o Construtor de BigDecimal ao invés de double
	BigDecimal b2 = new BigDecimal("3.305"); //Passe String para o Construtor de BigDecimal ao invés de double
	BigDecimal result = b1.multiply(b2);
	System.out.println(result); //mostra "33.050"
1 curtida

Obrigado Douglas-Silva pela dica. Obrigado TerraSkill, respondeu a minha dúvida. Mas permitem-me um desabafo. Tenho 46 anos e sou engenheiro de profissão. Dei um pouquinho de programação (Pascal) na faculdade faz 25 anosl. Nunca precisei de programar na minha profissão tirando uma ou outra macro em excel. Voltei ao estudo agora por simples curiosidade. E dizem-me que em 2017 os programas informáticos não conseguem fazer a multiplicação de 10*3.305 correctamente??? E que é preciso truques para apresentar o resultado certo? Percebo que é um limitação de raiz mas mesmo assim…Faz-me alguma confusão.

In pure math, every decimal has an equivalent bicimal. In floating-point math, this is just not true.

Esses problemas de implementar matemática em computação existem desde o começo, e provavelmente não serão resolvidos. Várias coisas na matemática exigiriam coisas impossíveis de serem feitas, porque exigiriam processamento infinito e/ou armazenamento infinito

1 curtida

Exatamente. É uma limitação dos modelos computacionais atuais, que nem sempre é perceptível em situações comuns, mas pode causar alguns problemas em grande escala.

Abraço.

1 curtida