Tipo float e double

Porque o java não aceita a seguinte declaração??
float f = 1.3;

1 curtida

Porque o valor 1.3 é por padrão double em java. Pra que você possa fazer essa atribuição é necessário fazer o casting que pode ser de duas formas:

float f = (float)1.3;

ou

float f = 1.3F;

que funcionam da mesma forma. essa atribuição funcionaria se fosse feito da seguinte forma:

double f = 1.3;
2 curtidas

ops:

aproveitando a pergunta
ontem estava mexendo com parametros e reparei uma coisa se tenho um metodo

double saldo; Conta(){ atualiza(saldo) }
e pegar na funcao um float ou mesmo um int
ele nao deixa, acredito que porque ocorre perda de dados de precisão, depreciamento, nem sei se existe isso
do double para float, tipo este aqui que deu errado pegando float de double

float atualiza(float depositoInicial) { depositoInicial = s.nextFloat(); //eu sei que deve ser double para valores,mas so para aprender coloquei outro tipo no caso float!! atualizaSaldo += depositoInicial; return atualizaSaldo; //quero que seja float //o metodo atualiza nao deve ter o atributo saldo como float? }
a variavel double la em cima,

  1. é o valor que a função irá usar?
  2. ou o valor que a função vai retornar?
    neste caso ela retorna um float atualizaSaldo e passa saldo que é double

ñ é aceita essa passagem de parametro pelo mesmo motivo que ñ aceita a atribuição, ao transformar um tipo double em float há perda de precisão, entao o compilador exige q vc faça isso explicitamente com um cast, algo como “prove pra mim que vc sabe oq está fazendo”

e sobre sua pergunta, ‘saldo’ é passado como parametro, entao o valor em ‘saldo’ é atribuido a ‘depositoInicial’

O valor que a função irá usar é o saldo da primeira linha, mas seria interessante passar por parâmetro:

void Conta(double saldo){ atualiza(saldo); }

Pra retorna um valor vc deve colocar o tipo do retorno entre o modificador e nome da função na declaração, e em pelo menos 1 lugar deve ter um return dentro da função:

double Conta(double saldo){ return atualiza(saldo); //aqui a função atualiza deve retornar o mesmo tipo pra dar certo //eu não testei o código }

Em java existe as classes utilitárias conhecidas com wrapper e elas servem pra fazer operações básicas como essa de conversão. por exemplo.

para um double existe uma classe wrapper chamada Double que possui uma operação de conversão de double pra float. Por exemplo:

double saldo = 1.3;

Double d = new Double(saldo);

float depositoInicial = d.floatValue();

cada tipo primitivo possui sua classe wrapper que possuem diversas opções de conversão.

vlw

[quote=remixlara]Porque o valor 1.3 é por padrão double em java. Pra que você possa fazer essa atribuição é necessário fazer o casting que pode ser de duas formas:

float f = 1.3F;

Essa operação não é um casting, mas uma especificação do tipo do literal.
Com essa declaração você diz que aquele 1.3 é um float. O compilador já criará do tipo float e não haverá perda de informação. Alguns castings (como o de double para float) exigem mais processamento do que só a reinterpretação do dado, por isso, essa forma é preferível ao casting direto.

Sem falar que é mais fácil de escrever e polui menos o código. :slight_smile:

boa… não tinha me atentado a isso. vc tem razão.

Os wrappers fazem dois tipos de conversão:

  1. Conversões com String;
  2. Conversões para int, em seu formato binário bruto.

Você não precisará nunca criar um wrapper com new para fazer conversões:

float valor = Float.parseFloat("1.13"); int bits = Float.floatToIntBits(1.13f);

Para converter double num float, sempre se faz através de cast:

double umDouble = 3.1415; float x = (float) umDouble;

O que você fez é uma enorme besteira. Você criou um objeto temporário. Atribuiu o valor passado por parâmetro a um double, que é um campo privado desse objeto. Depois chamou o método floatValue() que irá fazer o cast. É muito mais simples, rápido e fácil fazer o cast diretamente.

Os wrappers tem uma única finalidade: Representar o tipo primitivo quando um objeto for necessário. É o caso, por exemplo, em listas e sets, que só trabalham com objetos e não com tipos primitivos.

List<Double> lista = new ArrayList<Double>(); lista.add(Double.valueOf(1.13)); lista.add(Double.valueOf(2.14)); lista.add(Double.valueOf(3.1415));

No C++ e C# é possível criar listas de tipos primitivos:

std::vector<int> lista = new std::vector<int>(); //Valido em C++ IList<int> lista = new List<int>(); //Válido em C#

essas conversões com cast eu ja conhecia
uso em c++, mas achei estranho duas colocações

que nem o colega disse
1)‘saldo’ é passado como parametro, entao o valor em ‘saldo’ é atribuido a ‘depositoInicial’
pelo que aprendi se colocar private double saldo na declaração de variaveis
e colocar double saldo no metodo que utiliza, ou seja o mesmo nome para as variaveis
elas são variaveis ou atributos diferentes, com valores diferentes
São diferentes, ou depois do metodo executar ficam iguais?

2)e o casso de perda de precisão, existe?
porque se eu pegar um passar um char,int,short ou float
e em algum método pegar um double ex.

private int x; conta{ atualiza(x) } atualiza(double saldo)

este método é aceito e sem usar cast
(ai minha mãe :frowning: )

[quote=rodrigo.guri]que nem o colega disse
1)‘saldo’ é passado como parametro, entao o valor em ‘saldo’ é atribuido a ‘depositoInicial’
pelo que aprendi se colocar private double saldo na declaração de variaveis
e colocar double saldo no metodo que utiliza, ou seja o mesmo nome para as variaveis
elas são variaveis ou atributos diferentes, com valores diferentes
São diferentes, ou depois do metodo executar ficam iguais?
[/quote]

São diferentes. Dentro do método haverá a variável saldo (do método) e a this.saldo (da classe).
Elas não ficarão iguais.

[quote=rodrigo.guri]2)e o caso de perda de precisão, existe?
porque se eu pegar um passar um char,int,short ou float
e em algum método pegar um double ex.
[/quote]

O double é uma variável de 64bits, a maior do Java. Muito difícil perder precisão com ele. Tão difícil que o Java não exige cast para double.

Ressucitando o post para trazer a ele um conteúdo e também um pedido de horizonte para o Viny no tocante ao estudo deste fenômeno desagradável,
Estuando para certificação me deparei com o código abaixo:

public class Conversion
{
   public static void main(String[] args)
   {
     int i = 1234567890;
     float f = i;
     System.out.println(i - (int)f);
   }
}

e na realidade isso não imprime 0, pois tem a seguinte explicação:

Actually it prints -46. This is because the information was lost during the conversion from type int to type float as values of type float are not precise to nine significant digits.

Bom, passei no java ranch, e fiquei mais assustado ainda pois a explicação para tais fenomênos vem da "IEEE 754 floating-point encoding ", e nesse post vi uma explicação, mais não entendi o que acontece na dúvida abaixo:

post: http://www.coderanch.com/t/266307/java-programmer-SCJP/certification/Changes-out-put

[code]Hi All,
There are two examples related float precision. The only difference is the value of int i differs and both the example gives different results.

Please explain why?

Example 1:

int i = 1234567890;

float f = i;

int x = (int)f;

System.out.println(i == x); //Prints false

Example 2:
int i = Integer.MAX_VALUE;

float f = i;

int x = (int)f;

System.out.println(i == x); //Prints true [/code]

explicação do rapaiz la ultra mega informado:

[quote]posted quinta-feira, 15 de novembro de 2007 11:52 0
You’ll have to know something about IEEE 754 floating-point encoding to really understand this issue completely.

But briefly, the most important point here is that a float value cannot represent every int value precisely. floats are 32 bits long, and ints are also 32 bits long–but some of the 32 bits in the float are used to store the exponent (i.e. the “power”), leaving the float with only 23 bits to store the number’s actual significant digits (called the significand). One more significant digit will automatically be assumed for most numbers (see the IEEE 754 spec). Therefore, once your int value is large enough that it requires more than 24 significant binary digits to represent, you’re very likely to lose precision.

The two numbers you used in your tests (1234567890 and Integer.MAX_VALUE) are examples of such large numbers. As a result, when you cast them to a float, the JVM will choose the closest representable float value to your int value.

For 1234567890, the closest float value is 1234567936. Other int values “close” to 1234567890 will also be mapped to a float value of 1234567936. (To be precise, all ints from 1234567872 to 1234568000 will be mapped to this value.) This loss of precision causes the non-equality you observed when you cast the float back to an int.

Integer.MAX_VALUE (2147483647) is a more interesting case. This will get mapped to a float value of 2^31, or 2147483648. (All numbers from 2147483584 to 2147483776 will be mapped to this value.) However, when you cast this float value back to an int, this is larger than the maximum value of an int, so the JVM maps it back to Integer.MAX_VALUE. Hence your equality test prints “true”.

Note that your code will print “true” for int values that are exactly representable with a float. As already mentioned, 1234567936 is one such number. The next smaller one is 1234567808, and the next larger one is 1234568064.

Also, you won’t get any loss of precision converting an int to a double, because a double uses 52 bits for its significand. However, you’ll run into the same problem if you convert a long to a double.

[/quote]

Realmente as partes que não entendi foram estas:

e também

Tudo isso ficou muito confuso e acho que nunca mais vou conseguir usar tipos diferentes… pois sempre vou achar que tudo perde precisão… se puder Viny me dizer, se vou ter que ler toda a IEEE 754 floating-point encoding, ou como fazer para enter o conteúdo dessa discussão(o que ler, se tem livro que trata disso…) agradeço.

Primeiro passo, leia esse post onde eu explico como funciona o ponto flutuante (sem entrar nos detalhes da implementação do IEEE):
http://www.guj.com.br/java/261493-ponto-flutuante-e-ponto-fixo#1365723

Você só precisa entender que para um mesmo número de bits, os tipos de ponto flutuante sempre conseguem representar valores menores que os inteiros.
Eles tem menor precisão.

float tem 32 bits, ints também, portanto, haverá perdas de precisão ao converter int para float.
double tem 64 bits, como o long, portanto, haverá perdas de precisão ao converter de long para double.

Entretanto, a perda só ocorre em valores muito grandes.
Se você estiver trabalhando com valores de até 8 casas decimais, dificilmente terá problemas.

Números de ponto flutuante também são naturalmente imprecisos. Esse outro post explica o porque dessa imprecisão natural:

Viny, muito obrigado pela sua ajuda, vou fazer exatamente como você indicou, gostaria de saber por exemplo como eu faria a validação, por exemplo se vier um numero com
oito digitos então emito uma mensagem problemas com o casting…sendo assim vou ler o post, pois desta forma preciso saber realmente em que ponto vai acontecer isso…

Novamente muito obrigado pela sua atenção.

Em muitas aplicações, um número tão grande já vai ser restringido na interface (se for um valor financeiro, estamos falando em bilhões).
Para muita precisão, use o BigDecimal:


http://docs.oracle.com/javase/1.5.0/docs/api/java/math/BigDecimal.html

Legal, nem tinha imaginado isso, estou realmente afundado no interesse neste assunto, e vou ler todos os posts que você indicou e mais alguns se for preciso…
Viny estou lendo o segundo post, e gostaria de tirar uma dúvida… na sua explicação tem a seguinte afirmação:

2 = 10
0,5 = 1
2,5 = 10.1

uma dúvida, no caso na segunda linha o quer dizer? seria que 0,5 é o mesmo que 0,1X2^-1 que é o mesmo que 0,1 em binário, e sendo assim voce colocou ali o 1 que é o que será depois da vírgula?
Aproveitando a deixa vi que na calculadora do windows não consigo colocar o valor por exemplo 2,5, para converter em binário para assim corrigir minhas conversões…

Desculpa incomodar tanto…

Ops… a linha tava errada. O certo é
0,5 = 0.1

Já corrigi no post original também.

opa topico de 2010 em questão, quando eu fiz a pergunta nem sabia oque era parâmetros, hoje estou melhorzinho, rs :lol:
nunca deixem de responder perguntas basicas como estas, incentivam quem esta começando a continuar no java.

Viny, muito obrigado pela atenção.