Duvida em cast de long para double e float

5 respostas
M

As seguintes linhas de codigo compilam normalmente:

double d = 123L; float f = 123L;

a primeira pra mim esta tudo bem, ja que um double tem 64 bytes, assim como um long, mas a segunda linha eu achei que era pra dar erro, ja que voce esta tentando atribuir um valor de ate 64 bytes tem uma variavel de apenas 32 bytes…
alguem pode me explicar?

5 Respostas

ViniGodoy

O compilador pode determinar em tempo de compilação que 123 cabe perfeitamente em 32 bits… então, porque deveria dar erro?

M

double d = 9218868441522307072L; float f = 9218868441522307072L;

esse valor nao cabe em 32 bits, e mesmo assim não da erro

bigjoe

Basicamente, é o seguinte: a conversão se dá com base não no range de valor, mas sim na capacidade de representação dos bits. Ou, em termos da especificação Java, magnitude versus precisão.

Quando se faz a conversão de long para float, ocorre perda de PRECISÃO, mas não de MAGNITUDE. Se seu número é 9,218868441522307072 * 10^18, sua magnitude é 9 * 10^18. Quando você faz a conversão para float, este tipo primitivo é plenamente capaz de armazenar a magnitue ( 10^18 ), mas incorre em perda de precisão, arredondando implicitamente o valor convertido para um que tenha a precisão mais próxima possível do original.

Assim, a “mágica” ocorre nos bits menos significativos, que são sacrificados:

Olhe o código abaixo e o resultado das linhas:

float f = 9218868441522307072L;
System.out.println(f); //        resultado: 9.2188684E18
System.out.printf("%f", f); // resultado: 9218868437227405300,000000

Note que, no segundo exemplo, a partir do último bit significativo preciso exibido no primeiro exemplo, há perda de precisão, quando comparado com o original:
9218868[size=18] [color=red]4[/color][/size][telefone removido]
9.218868[size=18][color=red]4[/color][/size]E18
9218868[size=18][color=red]4[/color][/size][color=green][telefone removido][/color],000000 <-- note a perda de precisão (mas não de magnitude).

ViniGodoy

Ótima explicação.

Na verdade, nem poderia ser por causa do número de bits.

Um long usa muito mais bits para representar o valor numérico do que um float, ou mesmo um double.
O float é dividido no valor significativo (23 bits) e por um expoente (8 bits), mais um bit para o sinal.

Se fosse só pela quantidade de bits, haveria também erros muito chatos do compilador, como esse:

M

bigjoe:
Basicamente, é o seguinte: a conversão se dá com base não no range de valor, mas sim na capacidade de representação dos bits. Ou, em termos da especificação Java, magnitude versus precisão.

Quando se faz a conversão de long para float, ocorre perda de PRECISÃO, mas não de MAGNITUDE. Se seu número é 9,218868441522307072 * 10^18, sua magnitude é 9 * 10^18. Quando você faz a conversão para float, este tipo primitivo é plenamente capaz de armazenar a magnitue ( 10^18 ), mas incorre em perda de precisão, arredondando implicitamente o valor convertido para um que tenha a precisão mais próxima possível do original.

Assim, a “mágica” ocorre nos bits menos significativos, que são sacrificados:

Olhe o código abaixo e o resultado das linhas:

float f = 9218868441522307072L;
System.out.println(f); //        resultado: 9.2188684E18
System.out.printf("%f", f); // resultado: 9218868437227405300,000000

Note que, no segundo exemplo, a partir do último bit significativo preciso exibido no primeiro exemplo, há perda de precisão, quando comparado com o original:
9218868[size=18] [color=red]4[/color][/size][telefone removido]
9.218868[size=18][color=red]4[/color][/size]E18
9218868[size=18][color=red]4[/color][/size][color=green][telefone removido][/color],000000 <-- note a perda de precisão (mas não de magnitude).

entendi, so eh meio confuso essas regras, ja que pra atribuir um double para um float precisa de cast explicito, pois pode ocorrer perda de precisão, mas nesse caso ai nao precisa…

Criado 9 de setembro de 2009
Ultima resposta 9 de set. de 2009
Respostas 5
Participantes 3