web-dev-qa-db-fra.com

Type flottant et double en Java

Le type de données float est une virgule flottante IEEE 754 32 bits simple précision et le type de données double est une virgule flottante IEEE 754 64 bits double précision.

Qu'est-ce que ça veut dire? Et quand devrais-je utiliser float au lieu de double ou vice-versa?

189
Leo

La page Wikipedia est un bon point de départ.

Pour résumer:

  • float est représenté en 32 bits, avec 1 bit de signe, 8 bits d'exposant et 23 bits du significande (ou ce qui suit d'un numéro de notation scientifique: 2.33728 * 1012; 33728 est le significand).

  • double est représenté en 64 bits, avec 1 bit de signe, 11 bits d'exposant et 52 bits de significande.

Par défaut, Java utilise double pour représenter ses nombres à virgule flottante (donc un 3.14 littéral est saisi double). C'est également le type de données qui vous donnera une plage de nombres beaucoup plus large, je vous encourage donc vivement à l'utiliser au-dessus de float.

Certaines bibliothèques peuvent forcer votre utilisation de float, mais en général, à moins que vous ne puissiez garantir que votre résultat sera suffisamment petit pour tenir dans la plage de float , il est préférable d'opter pour double.

Si vous avez besoin d’exactitude - par exemple, vous ne pouvez pas avoir une valeur décimale inexacte (telle que 1/10 + 2/10), ou si vous utilisez rien avec une devise (par exemple, représentant 10,33 USD dans le système), utilisez un BigDecimal, qui peut supporter une quantité arbitraire de précision et gérer avec élégance de telles situations.

225
Makoto

Un flotteur vous donne environ. Précision 6-7 chiffres décimaux alors qu'un double vous donne env. 15-16. La plage de nombres est également plus grande pour les doubles.

Un double nécessite 8 octets d'espace de stockage, tandis qu'un float n'a besoin que de 4 octets.

66
Henry

Les nombres à virgule flottante, également appelés nombres réels, sont utilisés lors de l'évaluation d'expressions nécessitant une précision fractionnaire. Par exemple, des calculs tels que la racine carrée ou des caractères transcendants tels que le sinus et le cosinus donnent une valeur dont la précision nécessite un type à virgule flottante. Java implémente l'ensemble standard (IEEE – 754) de types et d'opérateurs à virgule flottante. Il existe deux types de types à virgule flottante, float et double, qui représentent respectivement des nombres à simple et à double précision. Leur largeur et leurs plages sont indiquées ici: 


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


float

Le type float spécifie une valeur simple précision qui utilise 32 bits de stockage. La précision simple est plus rapide sur certains processeurs et prend deux fois moins de place que la double précision, mais elle deviendra imprécise lorsque les valeurs sont très grandes ou très petites. Les variables de type float sont utiles lorsque vous avez besoin d'un composant fractionnaire, mais n'exigent pas un degré de précision élevé. 

Voici quelques exemples de déclarations de variable float:

float hightemp, lowtemp; 


double

La double précision, indiquée par le mot-clé double, utilise 64 bits pour stocker une valeur. La double précision est en réalité plus rapide que la simple précision sur certains processeurs modernes optimisés pour les calculs mathématiques à grande vitesse. Toutes les fonctions mathématiques transcendantes, telles que sin (), cos () et sqrt (), renvoient des valeurs doubles. Lorsque vous devez maintenir la précision sur de nombreux calculs itératifs ou manipuler des nombres de grande valeur, double est le meilleur choix.

13
Ye Win

Java semble néanmoins avoir tendance à utiliser double pour les calculs:

Exemple: le programme que j'ai écrit plus tôt dans la journée, les méthodes ne fonctionnaient pas lorsque j'utilisais float, mais fonctionnaient désormais très bien lorsque j'ai remplacé float par double (dans l'EDI NetBeans):

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;
    }
}
2
Raymond Wachaga

Selon les normes IEEE, float est une représentation 32 bits d'un nombre réel, tandis que double est une représentation 64 bits.

Dans les programmes Java, nous voyons généralement principalement l’utilisation du type de données double. Il s'agit simplement d'éviter les débordements, car la plage de nombres pouvant être gérée à l'aide du type de données double est supérieure à la plage utilisée lorsque float est utilisé.

De plus, lorsqu'une grande précision est requise, l'utilisation du double est encouragée. Peu de méthodes de bibliothèque mises en œuvre il y a longtemps requièrent encore l'utilisation du type de données float (c'est uniquement parce qu'il a été implémenté à l'aide de float, rien d'autre!).

Mais si vous êtes certain que votre programme nécessite de petits nombres et qu'aucun débordement ne se produira avec votre utilisation de float, l'utilisation de float améliorera grandement la complexité de votre espace, car les float nécessitent la moitié de la mémoire requise par double.

1
Rubal

Cela donnera une erreur:

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

/MyClass.Java:3: error: types incompatibles: conversion avec perte possible de double en float float a = 0,5;

Cela fonctionnera parfaitement bien

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

Cela fonctionnera également parfaitement bien

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

Reason : Java stocke par défaut les nombres réels en double pour assurer une plus grande précision. 

Double prend plus de place mais plus de précision lors du calcul et float prend moins de place mais moins de précision.

0
Himanshu Singh

Cet exemple montre comment extraire le signe (le bit le plus à gauche), l'exposant (les 8 bits suivants) et la mantisse (les 23 bits les plus à droite) d'un float en 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));

La même approche peut être utilisée pour les doubles (exposants 11 bits et mantisses 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édit: http://s-j.github.io/Java-float/

0
acohen