Tipo de dados flutuante e duplo em Java

220

O tipo de dados flutuante é um ponto flutuante IEEE 754 de precisão única de 32 bits e o tipo de dados duplo é um ponto flutuante IEEE 754 de precisão dupla de 64 bits.

O que isso significa? E quando devo usar float em vez de duplo ou vice-versa?

Leo
fonte
8
Você deve usar flutuadores em vez de dobrar quando o uso da memória for crítico. Se você precisar de cálculos mais precisos, use duplos.
Everv0id
12
@ Everv0id: Não tenho certeza de nenhuma situação em que a memória seja tão estreita que se tenha que sacrificar a precisão por espaço. (Você está usando Java , pelo amor de Deus ...) Pode haver algumas situações em que é necessário, mas na minha prática eu o vejo muito raramente. Se você quisesse explicar por que acha que é uma boa ideia, fornecer uma resposta com, por exemplo, seria uma adição valiosa.
22714 Makoto
en.wikipedia.org/wiki/IEEE_floating_point
Wundwin nascido em 22/12/14
5
@ Makoto, na verdade, nunca usei carros alegóricos, apenas dobra. Mas pode haver aplicações (em teoria) que devem manter grandes quantidades de números de ponto flutuante, portanto, o uso de memória 2x pode ser crítico. Em teoria, ofc; na prática, você sempre pode comprar outro servidor .
Everv0id
3
Usei números de precisão fixos de 4 e até 2 bytes para economizar memória, mas, a menos que você tenha bilhões deles, é improvável que valha a pena. O tempo que você leva para escrever "double" em vez de "float" (possui mais uma letra) vale 1000x mais que a memória extra que você usa, mas se usar em doublevez de floatevitar um bug relacionado à precisão, vale a pena .
Peter Lawrey

Respostas:

259

A página da Wikipedia é um bom lugar para começar.

Resumindo:

  • floaté representado em 32 bits, com 1 bit de sinal, 8 bits de expoente e 23 bits do significando (ou o que se segue de um número de notação científica: 2.33728 * 10 12 ; 33728 é o significando).

  • double é representado em 64 bits, com 1 bit de sinal, 11 bits de expoente e 52 bits de significando.

Por padrão, Java usa doublepara representar seus números de ponto flutuante (para que um literal 3.14seja digitado double). Também é o tipo de dados que fornecerá um intervalo de números muito maior, por isso incentivaria fortemente seu uso float.

Pode haver algumas bibliotecas que realmente forçar o uso de float, mas em geral - a menos que você pode garantir que seu resultado será suficientemente pequeno para caber em float's gama prescrita , então é melhor optar com double.

Se você precisar de precisão - por exemplo, não poderá ter um valor decimal impreciso (como 1/10 + 2/10) ou estiver fazendo algo com moeda (por exemplo, representando US $ 10,33 no sistema), use a BigDecimal, que pode suportar uma quantidade arbitrária de precisão e lida com situações como essa de maneira elegante.

Makoto
fonte
4
233728 == mantissa não é um exemplo? Quero dizer, onde mais a parte inteira é armazenada?
21716
1
@ mathguy54: Em notação científica, 2 seria o inteiro inteiro e 0,33328 seria a mantissa. Aqui está uma referência a isso.
Makoto
5
Eu estava pesquisando informações sobre carros alegóricos e duplos e achei isso e precisava comentar: se você está fazendo algo com uma moeda que não envolve centavos fracionários, usar o BigDecimal é ridículo. Moeda comum são dados discretos, portanto, você deve usar um tipo de dados inteiro. (Este é um dos erros mais comuns cometidos por jovens programadores - desde que use um separar dólares de centavos, eles acham que é um valor de ponto flutuante não é...)
Trixie Lobo
2
@TrixieWolf, você poderia ser mais específico, você propôs usar dois números inteiros (partes inteiras e decimais)? E você está falando sobre moeda comum, e o resto? Alguma quantia é avaliada com 6 decimais, então você não pode simplesmente *100. Por favor, você tem um ponto aqui, mas você poderia ser mais preciso :)
AxelH
9
@AxelH Exceto pelos meios de cálculos financeiros em que centavos fracionários podem existir, o dinheiro é sempre discreto. Você usaria um tipo inteiro para armazenar os dados. Portanto, US $ 5,34 seriam armazenados como 534. A parte do dólar é val / 100 em matemática de números inteiros e os centavos são val% 100 em matemática de números inteiros, em que% se refere à operação restante. Para dinheiro com mais casas além do decimal, ele ainda deve ser armazenado como integral porque é discreto. Mesmo que não seja discreto, geralmente você desejará recuar para um armazenamento discreto na maioria das vezes, porque é preciso, para que você não perca dinheiro com erros de arredondamento.
Trixie Wolf
72

Um flutuador oferece aprox. Precisão de 6 a 7 dígitos decimais, enquanto um duplo fornece aprox. 15-16. Além disso, o intervalo de números é maior para o dobro.

Um duplo precisa de 8 bytes de espaço de armazenamento, enquanto um flutuador precisa de apenas 4 bytes.

Henry
fonte
13

Os números de ponto flutuante, também conhecidos como números reais, são usados ​​ao avaliar expressões que requerem precisão fracionária. Por exemplo, cálculos como raiz quadrada ou transcendentais como seno e cosseno, resultam em um valor cuja precisão requer um tipo de ponto flutuante. Java implementa o conjunto padrão (IEEE-754) de tipos e operadores de ponto flutuante. Existem dois tipos de tipos de ponto flutuante, float e double, que representam números de precisão única e dupla, respectivamente. Sua largura e faixas são mostradas aqui:


   Name     Width in Bits   Range 
    double  64              1 .7e308 to 1.7e+308
    float   32              3 .4e038 to 3.4e+038


flutuador

O tipo float especifica um valor de precisão única que usa 32 bits de armazenamento. A precisão única é mais rápida em alguns processadores e ocupa metade do espaço da precisão dupla, mas se tornará imprecisa quando os valores forem muito grandes ou muito pequenos. Variáveis ​​do tipo float são úteis quando você precisa de um componente fracionário, mas não exige um alto grau de precisão.

Aqui estão alguns exemplos de declarações de variáveis ​​flutuantes:

float hightemp, baixa temperatura;


Duplo

A precisão dupla, como indicado pela palavra-chave double, usa 64 bits para armazenar um valor. A precisão dupla é realmente mais rápida do que a precisão única em alguns processadores modernos que foram otimizados para cálculos matemáticos de alta velocidade. Todas as funções matemáticas transcendentais, como sin (), cos () e sqrt (), retornam valores duplos. Quando você precisa manter a precisão de muitos cálculos iterativos ou manipular números de grande valor, o dobro é a melhor opção.

Ye Win
fonte
Esta resposta é claramente esclarecida quando devemos usar float e double.why não?
Ye Win
8
Nem os tipos floatnem doublesão mais usados ​​para moeda no Java, porque abrem a oportunidade para erros de arredondamento. Este artigo entra em mais detalhes: javapractices.com/topic/TopicAction.do?Id=13
PPartisan
1
"float pode ser útil ao representar dólares e centavos." - não, não, não, não. Nunca, nunca armazene moeda como flutuadores / duplos.
reduzindo a atividade
2

No entanto, o Java parece ter uma tendência a usar o dobro para cálculos:

Por exemplo, o programa que escrevi hoje, os métodos não funcionaram quando usei float, mas agora funcionam muito bem quando substituí o float por double (no NetBeans IDE):

package palettedos;
import java.util.*;

class Palettedos{
    private static Scanner Z = new Scanner(System.in);
    public static final double pi = 3.142;

    public static void main(String[]args){
        Palettedos A = new Palettedos();
        System.out.println("Enter the base and height of the triangle respectively");
        int base = Z.nextInt();
        int height = Z.nextInt();
        System.out.println("Enter the radius of the circle");
        int radius = Z.nextInt();
        System.out.println("Enter the length of the square");
        long length = Z.nextInt();
        double tArea = A.calculateArea(base, height);
        double cArea = A.calculateArea(radius);
        long sqArea = A.calculateArea(length);
        System.out.println("The area of the triangle is\t" + tArea);
        System.out.println("The area of the circle is\t" + cArea);
        System.out.println("The area of the square is\t" + sqArea);
    }

    double calculateArea(int base, int height){
        double triArea = 0.5*base*height;
        return triArea;
    }

    double calculateArea(int radius){
        double circArea = pi*radius*radius;
        return circArea;
    }

    long calculateArea(long length){
        long squaArea = length*length;
        return squaArea;
    }
}
Raymond Wachaga
fonte
Eu tive o mesmo problema hoje. Qual pode ser a razão por trás desse viés?
Shachi
2

Isso dará erro:

public class MyClass {
    public static void main(String args[]) {
        float a = 0.5;
    }
}

/MyClass.java:3: erro: tipos incompatíveis: possível conversão com perdas de double para float float a = 0,5;

Isso funcionará perfeitamente bem

public class MyClass {
    public static void main(String args[]) {
        double a = 0.5;
    }
}

Isso também funcionará perfeitamente bem

public class MyClass {
    public static void main(String args[]) {
        float a = (float)0.5;
    }
}

Razão : Java, por padrão, armazena números reais como o dobro para garantir maior precisão.

O Double ocupa mais espaço, mas é mais preciso durante o cálculo, e o float ocupa menos espaço, mas é menos preciso.

Himanshu Singh
fonte
1

De acordo com os padrões IEEE, float é uma representação de 32 bits de um número real, enquanto double é uma representação de 64 bits.

Nos programas Java, normalmente vemos o uso do tipo de dados duplo. É apenas para evitar estouros, pois o intervalo de números que pode ser acomodado usando o tipo de dados duplo é mais do que o intervalo quando o float é usado.

Além disso, quando é necessária alta precisão, o uso da dupla é incentivado. Poucos métodos de biblioteca que foram implementados há muito tempo ainda exigem o uso do tipo de dados float como uma obrigação (isso é apenas porque foi implementado usando float, nada mais!).

Mas se você tiver certeza de que seu programa requer números pequenos e não ocorrer um estouro com o uso do float, o uso do float melhorará bastante a complexidade do seu espaço, pois os floats exigem metade da memória, conforme exigido pelo dobro.

Rubal
fonte
0

Este exemplo ilustra como extrair o sinal (o bit mais à esquerda), o expoente (os 8 bits seguintes) e a mantissa (os 23 bits mais à direita) de um flutuador em Java.

int bits = Float.floatToIntBits(-0.005f);
int sign = bits >>> 31;
int exp = (bits >>> 23 & ((1 << 8) - 1)) - ((1 << 7) - 1);
int mantissa = bits & ((1 << 23) - 1);
System.out.println(sign + " " + exp + " " + mantissa + " " +
  Float.intBitsToFloat((sign << 31) | (exp + ((1 << 7) - 1)) << 23 | mantissa));

A mesma abordagem pode ser usada para o dobro (expoente de 11 bits e mantissa de 52 bits).

long bits = Double.doubleToLongBits(-0.005);
long sign = bits >>> 63;
long exp = (bits >>> 52 & ((1 << 11) - 1)) - ((1 << 10) - 1);
long mantissa = bits & ((1L << 52) - 1);
System.out.println(sign + " " + exp + " " + mantissa + " " +
  Double.longBitsToDouble((sign << 63) | (exp + ((1 << 10) - 1)) << 52 | mantissa));

Crédito: http://sj.github.io/java-float/

acohen
fonte
0

Você deve usar o dobro em vez de flutuar para cálculos precisos e flutuar em vez de dobrar ao usar cálculos menos precisos. Float contém apenas números decimais, mas double contém um número de ponto flutuante de precisão dupla IEEE754, facilitando a contenção e o cálculo de números com mais precisão. Espero que isto ajude.

boi yeet
fonte
0

Em cálculos regulares de programação, não usamos float. Se garantirmos que o intervalo de resultados esteja dentro do intervalo do tipo de dados flutuantes, poderemos escolher um tipo de dados flutuantes para economizar memória. Geralmente, usamos o dobro por duas razões: -

  • Se quisermos usar o número de ponto flutuante como tipo de dados flutuante, o responsável pela chamada do método deve explicitamente sufocar F ou f, porque, por padrão, todo número de ponto flutuante é tratado como duplo. Aumenta a carga para o programador. Se usarmos um número de ponto flutuante como tipo de dados duplo, não precisaremos adicionar nenhum sufixo.
  • Float é um tipo de dados de precisão única, que ocupa 4 bytes. Portanto, em grandes cálculos, não obteremos um resultado completo. Se escolhermos o tipo de dados duplo, ele ocupa 8 bytes e obteremos resultados completos.

Os tipos de dados flutuante e duplo foram projetados especialmente para cálculos científicos, onde os erros de aproximação são aceitáveis. Se a precisão é a preocupação mais anterior, é recomendável usar a classe BigDecimal em vez de tipos de dados flutuantes ou duplos. Fonte: - Tipos de dados flutuantes e duplos em Java

Rocco Jerry
fonte