Type de données flottant et double en Java
Le type de données float est un virgule flottante IEEE 754 32 bits à simple précision et le type de données double est un 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?
7 réponses
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 significand (ou ce qui suit d'un nombre de notation scientifique: 2.33728*1012; 33728 est le significand).double
est représenté en 64 bits, 1 bit de signe, 11 bits d'exposant et 52 bits de significande.
Par défaut, Java utilise double
pour représenter son virgule flottante chiffres (donc un littéral 3.14
est tapé double
). C'est aussi le type de données qui vous donnera une plage de nombres beaucoup plus grande, donc j'encourage fortement son utilisation sur float
.
Il peut y avoir certaines bibliothèques qui forcent réellement votre utilisation de float
, mais en général-à moins que vous ne puissiez garantir que votre résultat sera assez petit pour tenir dans float
plage prescrite , Alors il est préférable d'opter pour double
.
Si vous avez besoin de précision-pour par exemple, vous ne pouvez pas avoir une valeur décimale inexacte (comme 1/10 + 2/10
), ou vous faites n'importe quoi avec de la monnaie (par exemple, représentant $10,33 dans le système), puis utilisez un BigDecimal
, qui peut prendre en charge une quantité arbitraire de précision et gérer des situations comme ça avec élégance.
Un flotteur vous donne env. 6-7 chiffres décimaux précision tandis qu'un double vous donne env. 15-16. Aussi la gamme de nombres est plus grande pour le double.
Un double a besoin de 8 octets d'espace de stockage tandis qu'un float n'a besoin que de 4 octets.
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 transcendantaux tels que le sinus et le cosinus, aboutissent à une valeur dont la précision nécessite un type à virgule flottante. Java implémente l'ensemble standard (IEEE–754) des types et opérateurs de floatingpoint. Il existe deux types de types à virgule flottante, float et double, qui représentent des nombres à simple et à double précision, respectivement. 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 de précision unique qui utilise 32 bits de stockage. La précision unique est plus rapide sur certains processeurs et prend la moitié de l'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. Par exemple, float peut être utile lorsque vous représentez des dollars et des cents.
Voici quelques exemples de déclarations de variables flottantes:
Float hightemp, lowtemp;
double
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 précision unique sur certains processeurs modernes qui ont été optimisés pour les calculs mathématiques à grande vitesse. Toutes les fonctions mathématiques transcendantales, telles que le péché( ), cos () et sqrt () renvoient des valeurs doubles. Lorsque vous devez maintenir la précision sur de nombreux calculs itératifs, ou manipulez des nombres de grande valeur, le double est le meilleur choix.
Java semble avoir un biais vers l'utilisation de double pour les calculs néanmoins:
Cas par cas le programme que j'ai écrit plus tôt aujourd'hui, les méthodes ne fonctionnaient pas quand j'utilisais float, mais fonctionnent maintenant très bien quand j'ai substitué float avec 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;
}
}
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 de double type de données. C'est juste pour éviter les débordements car la plage de nombres qui peuvent être logés en utilisant le type de données double est plus que la plage lorsque float est utilisé.
Également lorsque la haute précision est nécessaire, l'utilisation de double est encouragée. Peu de méthodes de bibliothèque qui ont été implémentées il y a longtemps nécessite 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, l'utilisation de float améliorera en grande partie la complexité de votre espace car les flotteurs nécessitent la moitié de la mémoire requise par double.
Cet exemple illustre 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 flottant 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://s-j.github.io/java-float/
Cela donnera une erreur:
public class MyClass {
public static void main(String args[]) {
float a = 0.5;
}
}
/Maclasse.java: 3: Erreur: types incompatibles: conversion avec perte possible de double à float float A = 0,5;
Cela fonctionne parfaitement bien
public class MyClass {
public static void main(String args[]) {
double a = 0.5;
}
}
Cela fonctionnera également parfaitement beaux -
public class MyClass {
public static void main(String args[]) {
float a = (float)0.5;
}
}
Raison : Java stocke par défaut les nombres réels comme doubles pour assurer une plus grande précision.
Double prend plus d'espace mais plus précis pendant le calcul et float prend moins d'espace mais moins précise.