Flottant et double type de données en Java

220

Le type de données flottant est un point flottant IEEE 754 32 bits simple précision et le type de données double est un point flottant IEEE 754 64 bits double précision.

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

Leo
la source
8
Vous devez utiliser des flottants au lieu de double lorsque l'utilisation de la mémoire est critique. Si vous avez besoin de calculs plus précis, utilisez des doubles.
Everv0id
12
@ Everv0id: Je ne suis sûr d'aucune situation dans laquelle la mémoire était si étroite qu'il fallait sacrifier la précision pour l'espace. (Vous utilisez Java , pour l'amour du ciel ...) Il peut y avoir certaines situations où cela est nécessaire, mais dans ma pratique, je l'ai vu très rarement. Si vous vouliez expliquer pourquoi vous pensez que c'est une bonne idée, fournir une réponse par exemple serait un ajout valable.
Makoto
5
@Makoto en fait, je n'ai jamais utilisé de flotteurs, seulement des doubles. Mais il pourrait y avoir des applications (en théorie) qui devraient conserver de grandes quantités de nombres à virgule flottante, donc l'utilisation de la mémoire 2x pourrait être critique. En théorie, ofc; en pratique, vous pouvez toujours acheter un autre serveur .
Everv0id
3
J'ai utilisé des nombres à précision fixe de 4 octets et même de 2 octets pour économiser de la mémoire, mais à moins que vous n'en ayez des milliards, il est peu probable que cela en vaille la peine. Le temps qu'il vous faut pour écrire "double" au lieu de "float" (il a une lettre de plus) vaut 1000 fois plus que la mémoire supplémentaire que vous utilisez, mais si l'utilisation doubleplutôt que floatvous évite un bug lié à la précision, cela en vaut la peine .
Peter Lawrey

Réponses:

259

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

Pour résumer:

  • floatest représenté en 32 bits, avec 1 bit de signe, 8 bits d'exposant et 23 bits de la significande (ou ce qui découle d'un numéro de notation scientifique: 2.33728 * 10 12 ; 33728 est la significande).

  • 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 doublepour représenter ses chiffres à virgule flottante (donc un littéral 3.14est typé double). C'est également le type de données qui vous donnera une plage de nombres beaucoup plus grande, donc j'encourage fortement son utilisation float.

Il peut y avoir certaines bibliothèques qui forcent votre utilisation float, mais en général - à moins que vous ne puissiez garantir que votre résultat sera suffisamment petit pour tenir dans floatla plage prescrite , alors il est préférable d'opter avec double.

Si vous avez besoin de précision - par exemple, vous ne pouvez pas avoir une valeur décimale inexacte (comme 1/10 + 2/10), ou vous faites quoi que ce soit avec de la monnaie (par exemple, représentant 10,33 $ dans le système), alors utilisez un BigDecimal, qui peut prendre en charge un quantité arbitraire de précision et gérer des situations comme ça avec élégance.

Makoto
la source
4
N'est-ce pas 233728 == mantisse dans l'exemple donné? Je veux dire, où d'autre est la partie entière stockée?
JaLoveAst1k
1
@ mathguy54: En notation scientifique, 2 serait l'entier entier et .33728 serait la mantisse. Voici une référence à cela.
Makoto
5
Je cherchais des informations sur les flottants et les doubles et j'ai trouvé cela et je devais commenter: si vous faites quoi que ce soit avec de la monnaie qui n'implique pas des cents fractionnaires, utiliser BigDecimal est ridicule. La devise commune est les données discrètes, vous devez donc utiliser un type de données entier. (C'est l'une des erreurs les plus courantes commises par les jeunes programmeurs - puisque nous utilisons a. Pour séparer les dollars des cents, ils pensent que c'est une valeur à virgule flottante. Ce n'est pas le cas.)
Trixie Wolf
2
@TrixieWolf, pourriez-vous être plus précis, avez-vous proposé d'utiliser deux entiers (entier et décimal)? Et vous parlez de monnaie commune, qu'en est-il du reste? Certains montants sont évalués avec 6 décimales, vous ne pouvez donc pas simplement *100. S'il vous plaît, vous avez un point ici, mais pourriez-vous être plus précis :)
AxelH
9
@AxelH Excepté les intermédiaires des calculs financiers où des cents fractionnaires peuvent exister, l'argent est toujours discret. Vous utiliseriez un type entier pour stocker les données. Ainsi, 5,34 $ seront stockés sous la forme 534. La portion en dollars est val / 100 en mathématiques entières et les cents sont val% 100 en mathématiques entiers, où% se réfère à l'opération restante. Pour l'argent avec plus de places après la décimale, il doit toujours être stocké comme intégral car il est discret. Même s'il n'est pas discret, vous voudrez souvent revenir à un stockage discret la plupart du temps car il est précis afin de ne pas perdre d'argent en raison des erreurs d'arrondi.
Trixie Wolf
72

Un flotteur vous donne env. Précision de 6 à 7 décimales tandis qu'un double vous donne env. 15-16. La plage de nombres est également plus grande pour le double.

Un double a besoin de 8 octets d'espace de stockage tandis qu'un flotteur n'a besoin que de 4 octets.

Henri
la source
13

Les nombres à virgule flottante, également appelés nombres réels, sont utilisés lors de l'évaluation des expressions qui nécessitent une précision fractionnaire. Par exemple, des calculs tels que la racine carrée ou des transcendantaux tels que le sinus et le cosinus donnent une valeur dont la précision requiert 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 les nombres simple et double précision. Leur largeur et leurs plages sont indiquées ici:


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


flotte

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 moitié moins d'espace que la double précision, mais 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 ne nécessitent pas un grand degré de précision.

Voici quelques exemples de déclarations de variables flottantes:

float hightemp, lowtemp;


double

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

Vous gagnez
la source
Cette réponse précise clairement quand nous devrions utiliser float et double. Pourquoi pas?
Vous gagnez
8
Ni les types floatni doubleles meilleurs ne sont utilisés pour les devises en Java, car ils ouvrent la possibilité d'erreurs d'arrondi. Cet article va plus en détail: javapractices.com/topic/TopicAction.do?Id=13
PPartisan
1
"float peut être utile pour représenter des dollars et des cents." - non, non, non, nononono. Jamais, jamais stocker de devises sous forme de flottants / doubles.
réduction de l'activité
2

Java semble néanmoins avoir un parti pris pour l'utilisation du double pour les calculs:

Par exemple, le programme que j'ai écrit plus tôt aujourd'hui, les méthodes ne fonctionnaient pas lorsque j'utilisais float, mais fonctionnent maintenant très bien lorsque je substituais float par double (dans l'IDE 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;
    }
}
Raymond Wachaga
la source
J'ai eu le même problème aujourd'hui. Quelle peut être la raison de ce biais?
Shachi
2

Cela donnera une erreur:

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

/MyClass.java:3: erreur: types incompatibles: possible conversion avec perte 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;
    }
}

Raison : Java par défaut stocke les nombres réels sous forme de double pour assurer une meilleure 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.

Himanshu Singh
la source
1

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 l'utilisation du type de données double. C'est juste pour éviter les débordements car la plage de nombres qui peut être prise en charge en utilisant le type de données double est plus que la plage lorsque float est utilisé.

De plus, lorsqu'une précision élevée est requise, l'utilisation du double est encouragée. Peu de méthodes de bibliothèque qui ont été implémentées il y a longtemps nécessitent toujours l'utilisation du type de données float comme un must (c'est seulement parce qu'il a été implémenté en utilisant float, rien d'autre!).

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

Rubal
la source
0

Cet exemple montre comment extraire le signe (le bit le plus à gauche), l'exposant (les 8 bits suivants) et la mantisse (les 23 bits le plus à droite) d'un flotteur 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 (exposant 11 bits et mantisse 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://sj.github.io/java-float/

acohen
la source
0

Vous devez utiliser le double au lieu de float pour des calculs précis et le float au lieu du double lorsque vous utilisez des calculs moins précis. Float ne contient que des nombres décimaux, mais double contient un nombre à virgule flottante double précision IEEE754, ce qui facilite le confinement et le calcul des nombres avec plus de précision. J'espère que cela t'aides.

boi yeet
la source
0

Dans les calculs de programmation réguliers, nous n'utilisons pas float. Si nous nous assurons que la plage de résultats se situe dans la plage de type de données flottantes, nous pouvons choisir un type de données flottantes pour économiser de la mémoire. Généralement, nous utilisons le double pour deux raisons: -

  • Si nous voulons utiliser le nombre à virgule flottante comme type de données flottant, l'appelant de la méthode doit explicitement suffixer F ou f, car par défaut, chaque nombre à virgule flottante est traité comme double. Cela augmente la charge pour le programmeur. Si nous utilisons un nombre à virgule flottante comme type de données double, nous n'avons pas besoin d'ajouter de suffixe.
  • Float est un type de données à simple précision, il occupe 4 octets. Par conséquent, dans les grands calculs, nous n'obtiendrons pas un résultat complet. Si nous choisissons un type de données double, il occupe 8 octets et nous obtiendrons des résultats complets.

Les types de données float et double ont été conçus spécialement pour les calculs scientifiques, où les erreurs d'approximation sont acceptables. Si la précision est la préoccupation la plus prioritaire, il est recommandé d'utiliser la classe BigDecimal au lieu des types de données float ou double. Source: - Float et doubles types de données en Java

Rocco Jerry
la source