Quelle est la bonne façon de parseFloat en Java

Je remarque des problèmes avec la précision de flottement de Java

Float.parseFloat("0.0065") - 0.001 // 0.0055000000134110451 new Float("0.027") - 0.001 // 0.02600000000700354575 Float.valueOf("0.074") - 0.001 // 0.07399999999999999999 

J’ai non seulement un problème avec Float mais aussi avec Double .

Quelqu’un peut-il expliquer ce qui se passe dans les coulisses et comment pouvons-nous obtenir un chiffre précis? Quelle serait la bonne façon de gérer cela quand on traite de ces problèmes?

Le problème est simplement que float a une précision finie; il ne peut pas représenter 0.0065 exactement. (Il en va de même pour le double , bien sûr: il est plus précis, mais toujours fini.)

Un autre problème, qui rend le problème ci-dessus plus évident, est que 0.001 est un double plutôt qu’un float , votre float devient donc un double pour effectuer la soustraction, et bien sûr, à ce stade, le système n’a aucun moyen de récupérer la précision manquante qu’un double aurait pu représenter pour commencer. Pour répondre à cela, vous écririez:

 float f = Float.parseFloat("0.0065") - 0.001f; 

en utilisant 0.001f au lieu de 0.001 .

Voir ce que chaque informaticien devrait savoir sur l’arithmétique en virgule flottante . Vos résultats me semblent corrects.

Si vous n’aimez pas le fonctionnement des nombres en virgule flottante, essayez plutôt BigDecimal .

Vous obtenez les bons résultats. Il n’existe pas de float tel que 0,027 exactement, ni de double . Vous obtiendrez toujours ces erreurs si vous utilisez float ou double .

float et double sont stockés en tant que fractions binarys : quelque chose comme 1/2 + 1/4 + 1/16 … Vous ne pouvez pas obtenir toutes les valeurs décimales pour être stockées exactement en tant que fractions binarys de précision finie. Ce n’est tout simplement pas possible mathématiquement.

La seule alternative consiste à utiliser BigDecimal , que vous pouvez utiliser pour obtenir des valeurs décimales exactes.

À partir de la page Tutoriels Java sur les types de données primitifs :

Un littéral à virgule flottante est de type float s’il se termine par la lettre F ou f ; sinon, son type est double et il peut éventuellement se terminer par la lettre D ou d .

Je pense donc que vos littéraux ( 0.001 ) sont doubles et que vous soustrayez les doubles des flottants.

Essayez ceci à la place:

 System.out.println((0.0065F - 0.001D)); // 0.005500000134110451 System.out.println((0.0065F - 0.001F)); // 0.0055 

… et vous aurez:

 0.005500000134110451 0.0055 

Ajoutez donc les suffixes F à vos littéraux et vous obtiendrez de meilleurs résultats:

 Float.parseFloat("0.0065") - 0.001F new Float("0.027") - 0.001F Float.valueOf("0.074") - 0.001F 

Je voudrais convertir votre float en chaîne, puis utiliser BigDecimal.

Ce lien l’explique bien

 new BigDecimal(Ssortingng.valueOf(yourDoubleValue)); 

N’utilisez pas le constructeur double BigDecimal, car vous obtiendrez toujours des erreurs

Longue histoire courte si vous avez besoin d’une précision arbitraire, utilisez BigDecimal sans float ni double. Vous verrez toutes sortes de problèmes d’arrondis de cette nature en utilisant float.

En passant, veillez à ne pas utiliser le constructeur float / double de BigDecimal, car le problème sera le même. Utilisez plutôt le constructeur Ssortingng.

Le point flottant ne peut pas représenter avec précision les nombres décimaux. Si vous avez besoin d’une représentation précise d’un nombre en Java, vous devez utiliser la classe java.math.BigDecimal:

 BigDecimal d = new BigDecimal("0.0065");