recherche
MaisonJavajavaDidacticielExplication détaillée d'exemples de perte de float et de double précision en Java

1.La plage de valeurs de int, float, long, double en java

[java] view plain copy

public class TestOutOfBound {

public static void main ( String[] args) {

System.out.println(Integer.MAX_VALUE-(-Integer.MAX_VALUE)); //Débordement de mémoire

System.out . println(Integer.MAX_VALUE); //2 à la puissance 31 -1, 10 chiffres, environ 2 milliards, ce qui n'est peut-être pas suffisant pour l'argent

System.out.println(Integer.MIN_VALUE) ; //Négatif 2 élevé à la puissance 31

System.out.println(Long.MAX_VALUE); //2 élevé à la puissance 64 - 1,19 chiffres, ce qui est très grand et peut être utilisé pour de l'argent . Ci-dessus

System.out.println(Long.MIN_VALUE); //Négatif 2 à la 64e puissance

System.out.println(Float.MAX_VALUE); //2 à la 128e ; power Square -1, 38 chiffres, deux fois plus longs Ceci est principalement utilisé pour des opérations mathématiques simples et précises

System.out.println(Float.MIN_VALUE);

System.out.println(Double.MAX_VALUE); //2 à la puissance 1024 - 1 308 chiffres, soit 10 fois le nombre de chiffres flottants Il est principalement utilisé pour les opérations complexes et les opérations astronomiques

System.out.println(Double.MIN_VALUE); //2 élevé à la puissance -1074

}

}

2.Problème de perte de flottement et de double précision

Exemple :

[java] afficher la copie simple

Exemple : double résultat = 1,0 - 0,9

Inutile de dire ce résultat, nous le connaissons tous, 0,09999999999999998

Pourquoi ce problème se produit-il ? C'est un problème qui se produit en Java et dans d'autres langages informatiques. se produit. Question :
Les types float et double sont principalement conçus pour les calculs scientifiques et les calculs techniques. Ils effectuent une arithmétique binaire à virgule flottante, soigneusement conçue pour fournir des calculs approximatifs rapides avec une grande précision sur une large plage de nombres. Cependant, ils ne fournissent pas de résultats totalement précis et ne doivent pas être utilisés pour des calculs exacts. Les types float et double sont particulièrement inadaptés aux opérations monétaires, car il est impossible pour un float ou un double de représenter avec précision 0,1 ou toute autre puissance négative de 10 (en fait, la raison est très simple. Peut-il être représenté avec précision au format décimal ? système ? Qu’en est-il de 1/3 ? Le même système binaire ne peut pas représenter avec précision 1/10).

Les opérations en virgule flottante sont rarement précises et des erreurs se produiront tant qu'elles dépassent la plage que la précision peut représenter. L’erreur se produit souvent non pas à cause de la taille du nombre, mais à cause de la précision du nombre. Par conséquent, les résultats produits sont proches mais pas égaux aux résultats souhaités. Soyez particulièrement prudent lorsque vous utilisez float et double pour des opérations exactes.

Analysons maintenant en détail pourquoi les opérations à virgule flottante entraînent une perte de précision ?



[java] view plain copy

Nous devons d'abord répondre aux deux questions suivantes :

(1) Comment convertir des entiers décimaux en nombres binaires

L'algorithme est très simple. Par exemple, 11 est exprimé sous forme de nombre binaire :

11/2=5 de plus de 1 5/2=2 de plus de 1

2/2 = 1 restant 0

1/2 = 0 余 1

0 fin La représentation binaire de 11 est (de bas en haut) : 1011

Une chose à mentionner ici : tant que le résultat après division est 0, c'est fini Pensez-y, tous les entiers divisés par 2 donneront certainement 0. En d’autres termes, l’algorithme qui convertit tous les entiers en nombres binaires continuera-t-il dans une boucle infinie ? Absolument pas. Les entiers peuvent toujours être représentés avec précision en binaire, mais les décimales ne le sont pas nécessairement.

(2) Comment convertir des nombres décimaux en nombres binaires

L'algorithme consiste à multiplier par 2 jusqu'à ce qu'il n'y ait plus de décimales. Par exemple, 0,9 est exprimé sous forme de nombre binaire

0,9*2=1,8 Prenez la partie entière 1

0,8 (partie fractionnaire de 1,8 )* 2=1.6 Obtenez la partie entière 1

0.6*2=1.2 Obtenez la partie entière 1

0.2*2=0.4 Prenez la partie entière 0

0,4*2=0,8 Prendre la partie entière 0

0,8*2=1,6 Prendre la partie entière 1

0,6*2 = 1,2 Prendre la partie entière 0

......... 0,9 binaire indiqué (de haut en bas) : 1100100100100 .....

Remarque : Le processus de calcul ci-dessus est une boucle, c'est-à-dire que*2 n'éliminera jamais la partie décimale, donc l'algorithme sera infini. Évidemment, la représentation binaire des décimales est parfois impossible à être précise. En fait, la raison est très simple. Peut-on représenter avec précision 1/3 dans le système décimal ? De même, le système binaire ne peut pas représenter avec précision 1/10. Cela explique également pourquoi la soustraction à virgule flottante pose le problème d'une perte de précision « inépuisable ».


3. Solution 1 :


Si cela ne vous dérange pas d'enregistrer vous-même le point décimal et que la valeur est pas grand, Ensuite, vous pouvez utiliser des types de base tels que long et int. Que vous utilisiez int ou long dépend de la taille de la plage numérique impliquée. L'inconvénient est que vous devez gérer vous-même la virgule décimale. utiliser des centimes pour calculer la monnaie au lieu du yuan (implique uniquement l'ajout d'une réduction).

Par exemple :

[java] view plain copy

int resultInt = 10 - 9

double result = (double) resultInt / 100; / /Au final, vous contrôlez vous-même le point décimal

4. Solution 2 :

Utilisez BigDecmal, et vous devez utiliser le type String dans les paramètres de construction.

Une solution est donnée dans le livre "Effective Java". Le livre souligne également que float et double ne peuvent être utilisés que pour des calculs scientifiques ou techniques. Dans des calculs précis tels que les calculs commerciaux, nous devons utiliser java.math.BigDecimal.

La classe BigDecimal a 4 méthodes. Nous ne nous soucions que des méthodes utiles pour des calculs précis de données à virgule flottante, c'est-à-dire

BigDecimal(double value) // Convertir des données doubles. En données de type BigDecimal

L'idée est très simple. Nous convertissons d'abord les données de type double en données BigDecimal via la méthode BigDecimal (valeur double), puis nous pouvons effectuer des calculs précis normalement. Une fois le calcul terminé, nous pouvons effectuer certains traitements sur les résultats, comme arrondir les résultats qui ne peuvent pas être divisés. Enfin, le résultat est reconverti des données BigDecimal en données doubles.

Cette idée est correcte, mais si vous regardez de plus près la description détaillée de BigDecimal dans l'API, vous saurez que si des calculs précis sont requis, nous ne pouvons pas utiliser double directement, mais devons utiliser String pour construire GrosDécimal. Par conséquent, nous commençons à nous soucier d'une autre méthode de la classe BigDecimal, à savoir la méthode BigDecimal(String value) qui peut nous aider à effectuer correctement des calculs précis.

// BigDecimal (String value) peut convertir les données String en données BigDecimal

Alors voici le problème, imaginez-le, si nous voulons faire une opération d'addition de données à virgule flottante, nous devons d'abord convertir les deux nombres à virgule flottante en données String, puis utiliser BigDecimal (valeur String) pour construire un BigDecimal , puis Pour appeler la méthode add sur l'un d'eux, passez l'autre en paramètre, puis convertissez le résultat de l'opération (BigDecimal) en un nombre à virgule flottante. Si vous devez faire cela à chaque fois que vous effectuez des calculs sur des données à virgule flottante, pouvez-vous supporter un processus aussi fastidieux ? Au moins, je ne peux pas. La meilleure façon est donc d’écrire une classe et d’effectuer ces processus de conversion fastidieux dans la classe. De cette façon, lorsque nous devons effectuer des calculs de données en virgule flottante, il nous suffit d'appeler cette classe. Certains experts sur Internet nous ont fourni un outil de classe Arith pour réaliser ces opérations de conversion. Il fournit les méthodes statiques suivantes, qui peuvent compléter les opérations d'addition, de soustraction, de multiplication et de division de données à virgule flottante et arrondir les résultats :

public static double add(double v1,double v2)
public double sous statique (double v1, double v2)
public statique double mul (double v1, double v2)
public statique double div (double v1, double v2)
public statique double div (double v1, double v2,int scale)
public static double round(double v, int scale)

Le code source d'Arith sera joint ci-dessous. Il vous suffit de le compiler et de le sauvegarder lorsque vous souhaitez effectuer un flottement. calculs de points, dans votre En important la classe Arith dans le programme source, vous pouvez utiliser les méthodes statiques ci-dessus pour effectuer des calculs précis de nombres à virgule flottante.

Annexe : Code source d'Arith

[java] afficher la copie simple

importer java.math.BigDecimal

/**

* Étant donné que les types simples de Java ne peuvent pas effectuer d'opérations précises sur les nombres à virgule flottante, cette classe utilitaire fournit des opérations

* précises sur les nombres à virgule flottante, notamment l'addition, la soustraction, la multiplication, la division et l'arrondi.

*/

classe publique Arith{

//Précision de l'opération de division par défaut

privé statique final int DEF_DIV_SCALE = 10;

//Cette classe ne peut pas être instanciée

private Arith(){

}

/**

* Fournit des opérations d'addition précises.

* @param v1 summand

* @param v2 addend

* @return somme de deux paramètres

*/ 

     double ajout statique public (double v1,double v2){                                                                                                                                          BigDecimal b2 = new BigDecimal(Double.toString(v2));

return b1.add(b2) .doubleValue();

} */

public static double sub(double v1,double v2){

BigDecimal b1 = new BigDecimal(Double.toString(v1) );

BigDecimal b2 = new BigDecimal(Double.toString(v2));

return b1.subtract(b2).doubleValue();

/**

* Fournit des opérations de soustraction précises.

* @param v1 Minuend

* @param v2 Minuend

* @return La différence entre les deux paramètres

*/

public static double mul(double v1,double v2){

BigDecimal b1 = new BigDecimal(Double.toString(v1)); 🎜>

BigDecimal b 2 = new BigDecimal(Double .toString(v2));

        return b1.multiply(b2).doubleValue();  

    }  

  

    /**

* Fournit des opérations de division (relativement) précises. Lorsque la division se produit, elle est précise à

* 10 décimales après la virgule, et les nombres suivants seront arrondis.

* @param v1 dividende

* @param v2 diviseur

* @return quotient des deux paramètres

*/  

    publique statique double div(double v1,double v2){  

        retourner div(v1,v2,DEF_DIV_SCALE);  

    }  

  

    /**

* Fournit des opérations de division (relativement) précises. Lorsqu'une division inépuisable se produit, la précision est spécifiée par le paramètre d'échelle

* et les nombres suivants sont arrondis.

* @param v1 dividend

* @param v2 diviseur

* L'échelle @param signifie qu'elle doit être précise à plusieurs décimales près.

* @return Le quotient des deux paramètres

*/  

    public static double div(double v1,double v2,int scale){  

        if(scale

             throw new IllegalArgumentException(  

                       " L'échelle doit être un entier positif ou zéro ");  

        }  

        BigDecimal b1 = new BigDecimal(Double.toString(v1));  

        BigDecimal b2 = new BigDecimal(Double.toString(v2));  

        return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();  

    }  

    /**

* Fournit un traitement précis de l'arrondi des décimales.

* @param v Le nombre à arrondir

* @param scale Combien de décimales conserver après la virgule

* @return Le résultat après arrondi

*/  

    public statique double tour (double v, échelle int){  

  

        if(scale

            throw new IllegalArgumentException(  

                "        " L'échelle doit être un entier positif ou zéro ");  

        }  

        BigDecimal b = new BigDecimal(Double.toString(v));  

        BigDecimal one = new BigDecimal("1");  

        return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();  

    }  

} ;  


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Comment utiliser Maven ou Gradle pour la gestion avancée de projet Java, la création d'automatisation et la résolution de dépendance?Comment utiliser Maven ou Gradle pour la gestion avancée de projet Java, la création d'automatisation et la résolution de dépendance?Mar 17, 2025 pm 05:46 PM

L'article discute de l'utilisation de Maven et Gradle pour la gestion de projet Java, la construction de l'automatisation et la résolution de dépendance, en comparant leurs approches et leurs stratégies d'optimisation.

How do I create and use custom Java libraries (JAR files) with proper versioning and dependency management?How do I create and use custom Java libraries (JAR files) with proper versioning and dependency management?Mar 17, 2025 pm 05:45 PM

L'article discute de la création et de l'utilisation de bibliothèques Java personnalisées (fichiers JAR) avec un versioning approprié et une gestion des dépendances, à l'aide d'outils comme Maven et Gradle.

Comment implémenter la mise en cache à plusieurs niveaux dans les applications Java à l'aide de bibliothèques comme la caféine ou le cache de goyave?Comment implémenter la mise en cache à plusieurs niveaux dans les applications Java à l'aide de bibliothèques comme la caféine ou le cache de goyave?Mar 17, 2025 pm 05:44 PM

L'article examine la mise en œuvre de la mise en cache à plusieurs niveaux en Java à l'aide de la caféine et du cache de goyave pour améliorer les performances de l'application. Il couvre les avantages de configuration, d'intégration et de performance, ainsi que la gestion de la politique de configuration et d'expulsion le meilleur PRA

Comment puis-je utiliser JPA (Java Persistance API) pour la cartographie relationnelle des objets avec des fonctionnalités avancées comme la mise en cache et le chargement paresseux?Comment puis-je utiliser JPA (Java Persistance API) pour la cartographie relationnelle des objets avec des fonctionnalités avancées comme la mise en cache et le chargement paresseux?Mar 17, 2025 pm 05:43 PM

L'article discute de l'utilisation de JPA pour la cartographie relationnelle des objets avec des fonctionnalités avancées comme la mise en cache et le chargement paresseux. Il couvre la configuration, la cartographie des entités et les meilleures pratiques pour optimiser les performances tout en mettant en évidence les pièges potentiels. [159 caractères]

Comment fonctionne le mécanisme de chargement de classe de Java, y compris différents chargeurs de classe et leurs modèles de délégation?Comment fonctionne le mécanisme de chargement de classe de Java, y compris différents chargeurs de classe et leurs modèles de délégation?Mar 17, 2025 pm 05:35 PM

Le chargement de classe de Java implique le chargement, la liaison et l'initialisation des classes à l'aide d'un système hiérarchique avec Bootstrap, Extension et Application Classloaders. Le modèle de délégation parent garantit que les classes de base sont chargées en premier, affectant la classe de classe personnalisée LOA

See all articles

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Commandes de chat et comment les utiliser
1 Il y a quelques moisBy尊渡假赌尊渡假赌尊渡假赌

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

Télécharger la version Mac de l'éditeur Atom

Télécharger la version Mac de l'éditeur Atom

L'éditeur open source le plus populaire

Adaptateur de serveur SAP NetWeaver pour Eclipse

Adaptateur de serveur SAP NetWeaver pour Eclipse

Intégrez Eclipse au serveur d'applications SAP NetWeaver.

Listes Sec

Listes Sec

SecLists est le compagnon ultime du testeur de sécurité. Il s'agit d'une collection de différents types de listes fréquemment utilisées lors des évaluations de sécurité, le tout en un seul endroit. SecLists contribue à rendre les tests de sécurité plus efficaces et productifs en fournissant facilement toutes les listes dont un testeur de sécurité pourrait avoir besoin. Les types de listes incluent les noms d'utilisateur, les mots de passe, les URL, les charges utiles floues, les modèles de données sensibles, les shells Web, etc. Le testeur peut simplement extraire ce référentiel sur une nouvelle machine de test et il aura accès à tous les types de listes dont il a besoin.

VSCode Windows 64 bits Télécharger

VSCode Windows 64 bits Télécharger

Un éditeur IDE gratuit et puissant lancé par Microsoft