public class doublePrecision {
public static void main(String[] args) {
double total = 0;
total += 5.6;
total += 5.8;
System.out.println(total);
}
}
Le code ci-dessus s'imprime:
11.399999999999
Comment pourrais-je obtenir ceci pour simplement imprimer (ou pouvoir l'utiliser comme) 11.4?
java
floating-point
double
precision
Déinumite
la source
la source
Réponses:
Comme d'autres l'ont mentionné, vous voudrez probablement utiliser la
BigDecimal
classe, si vous voulez avoir une représentation exacte de 11.4.Maintenant, une petite explication sur pourquoi cela se produit:
Les types primitifs
float
etdouble
en Java sont des nombres à virgule flottante , où le nombre est stocké sous forme de représentation binaire d'une fraction et d'un exposant.Plus spécifiquement, une valeur à virgule flottante double précision telle que le
double
type est une valeur 64 bits, où:Ces parties sont combinées pour produire une
double
représentation d'une valeur.(Source: Wikipedia: Double précision )
Pour une description détaillée de la façon dont les valeurs à virgule flottante sont gérées en Java, reportez-vous à la Section 4.2.3: Types, formats et valeurs à virgule flottante de la spécification du langage Java.
Les
byte
,char
,int
,long
types sont fichées numéros, qui sont representions exactes des nombres. Contrairement aux nombres à virgule fixe, les nombres à virgule flottante ne pourront parfois (supposer que "la plupart du temps") ne pourront pas renvoyer une représentation exacte d'un nombre. C'est la raison pour laquelle vous vous retrouvez à11.399999999999
la suite de5.6 + 5.8
.Lorsque vous avez besoin d'une valeur exacte, telle que 1.5 ou 150.1005, vous voudrez utiliser l'un des types à virgule fixe, qui sera en mesure de représenter le nombre exactement.
Comme cela a déjà été mentionné à plusieurs reprises, Java a une
BigDecimal
classe qui gère de très grands nombres et de très petits nombres.À partir de la référence API Java pour la
BigDecimal
classe:Il y a eu de nombreuses questions sur Stack Overflow concernant la question des nombres à virgule flottante et sa précision. Voici une liste de questions connexes susceptibles de vous intéresser:
Si vous voulez vraiment entrer dans les moindres détails des nombres à virgule flottante, jetez un coup d'œil à ce que tout informaticien devrait savoir sur l'arithmétique à virgule flottante .
la source
BigDecimal
soit beaucoup plus lent quedouble
dans ce cas, il n'est pas nécessaire car le double a 15 décimales de précision, il vous suffit d'arrondir.Lorsque vous entrez un nombre double, par exemple,
33.33333333333333
la valeur que vous obtenez est en fait la valeur de double précision représentable la plus proche, qui est exactement:Diviser cela par 100 donne:
qui n'est pas non plus représentable en tant que nombre à double précision, donc encore une fois, il est arrondi à la valeur représentable la plus proche, qui est exactement:
Lorsque vous imprimez cette valeur, elle est à nouveau arrondie à 17 chiffres décimaux, ce qui donne:
la source
Si vous souhaitez simplement traiter les valeurs sous forme de fractions, vous pouvez créer une classe Fraction contenant un champ de numérateur et de dénominateur.
Écrivez des méthodes pour ajouter, soustraire, multiplier et diviser ainsi qu'une méthode toDouble. De cette façon, vous pouvez éviter les flottants pendant les calculs.
EDIT: mise en œuvre rapide,
la source
numerator
etdenominator
devrait êtreint
s? Pourquoi voudriez-vous une précision en virgule flottante?Observez que vous auriez le même problème si vous utilisiez une arithmétique décimale à précision limitée et que vous vouliez traiter 1/3: 0,3333333333 * 3 est 0,999999999, et non 1,00000000.
Malheureusement, 5.6, 5.8 et 11.4 ne sont tout simplement pas des nombres ronds en binaire, car ils impliquent des quintes. Ainsi, leur représentation flottante n'est pas exacte, tout comme 0,3333 n'est pas exactement 1/3.
Si tous les nombres que vous utilisez sont des décimales non récurrentes et que vous voulez des résultats exacts, utilisez BigDecimal. Ou comme d'autres l'ont dit, si vos valeurs sont comme de l'argent dans le sens où elles sont toutes un multiple de 0,01 ou 0,001, ou quelque chose du genre, multipliez tout par une puissance fixe de 10 et utilisez int ou long (l'addition et la soustraction sont trivial: attention aux multiplications).
Cependant, si vous êtes satisfait du binaire pour le calcul, mais que vous voulez simplement imprimer les choses dans un format légèrement plus convivial, essayez
java.util.Formatter
ouString.format
. Dans la chaîne de format, spécifiez une précision inférieure à la précision totale d'un double. Pour 10 chiffres significatifs, disons que 11,399999999999 est 11,4, le résultat sera donc presque aussi précis et plus lisible par l'homme dans les cas où le résultat binaire est très proche d'une valeur ne nécessitant que quelques décimales.La précision à spécifier dépend un peu de la quantité de calculs que vous avez fait avec vos nombres - en général plus vous en faites, plus l'erreur s'accumule, mais certains algorithmes l'accumulent beaucoup plus rapidement que d'autres (ils sont appelés "instables" car par opposition à «stable» en ce qui concerne les erreurs d'arrondi). Si tout ce que vous faites est d'ajouter quelques valeurs, je suppose que le fait de ne laisser qu'une décimale de précision réglera les choses. Expérience.
la source
Vous pouvez envisager d'utiliser la classe java.math.BigDecimal de java si vous avez vraiment besoin de mathématiques de précision. Voici un bon article d'Oracle / Sun sur le cas de BigDecimal . Bien que vous ne puissiez jamais représenter 1/3 comme quelqu'un l'a mentionné, vous pouvez avoir le pouvoir de décider exactement à quel point vous voulez que le résultat soit précis. setScale () est votre ami .. :)
Ok, parce que j'ai beaucoup trop de temps libre pour le moment, voici un exemple de code qui se rapporte à votre question:
et pour brancher ma nouvelle langue préférée, Groovy, voici un exemple plus soigné de la même chose:
la source
À peu près sûr que vous auriez pu en faire un exemple en trois lignes. :)
Si vous voulez une précision exacte, utilisez BigDecimal. Sinon, vous pouvez utiliser des nombres entiers multipliés par 10 ^ quelle que soit la précision souhaitée.
la source
Comme d'autres l'ont noté, toutes les valeurs décimales ne peuvent pas être représentées sous forme binaire car la valeur décimale est basée sur des puissances de 10 et binaire sur des puissances de deux.
Si la précision compte, utilisez BigDecimal, mais si vous voulez juste une sortie conviviale:
Te donnera:
la source
Vous vous heurtez à la limitation de précision du type double.
Java.Math possède des fonctionnalités arithmétiques de précision arbitraire.
la source
Vous ne pouvez pas, car 7.3 n'a pas de représentation finie en binaire. Le plus proche que vous pouvez obtenir est 2054767329987789/2 ** 48 = 7,3 + 1/1407374883553280.
Jetez un œil à http://docs.python.org/tutorial/floatingpoint.html pour plus d'explications. (C'est sur le site Web de Python, mais Java et C ++ ont le même «problème».)
La solution dépend exactement de votre problème:
la source
la source
Utilisez java.math.BigDecimal
Les doubles sont des fractions binaires en interne, de sorte qu'ils ne peuvent parfois pas représenter des fractions décimales à la décimale exacte.
la source
Multipliez tout par 100 et stockez-le en centimes.
la source
Les ordinateurs stockent les nombres en binaire et ne peuvent pas réellement représenter des nombres tels que 33,333333333 ou 100,0 exactement. C'est l'une des choses délicates à propos de l'utilisation des doubles. Vous devrez simplement arrondir la réponse avant de la montrer à un utilisateur. Heureusement, dans la plupart des applications, vous n'avez pas besoin d'autant de décimales.
la source
Les nombres à virgule flottante diffèrent des nombres réels en ce que pour tout nombre à virgule flottante donné, il existe un nombre à virgule flottante immédiatement supérieur. Identique aux entiers. Il n'y a pas d'entier entre 1 et 2.
Il n'y a aucun moyen de représenter 1/3 comme un flotteur. Il y a un flotteur en dessous et un flotteur au-dessus, et il y a une certaine distance entre eux. Et 1/3 est dans cet espace.
Apfloat pour Java prétend fonctionner avec des nombres à virgule flottante de précision arbitraire, mais je ne l'ai jamais utilisé. Vaut probablement le détour. http://www.apfloat.org/apfloat_java/
Une question similaire a été posée ici avant la bibliothèque haute précision à virgule flottante Java
la source
Les doubles sont des approximations des nombres décimaux dans votre source Java. Vous voyez la conséquence de la discordance entre le double (qui est une valeur codée en binaire) et votre source (qui est codée en décimal).
Java produit l'approximation binaire la plus proche. Vous pouvez utiliser java.text.DecimalFormat pour afficher une valeur décimale plus belle.
la source
Utilisez un BigDecimal. Il vous permet même de spécifier des règles d'arrondi (comme ROUND_HALF_EVEN, qui minimisera l'erreur statistique en arrondissant au voisin pair si les deux sont de la même distance; c'est-à-dire que 1,5 et 2,5 sont arrondis à 2).
la source
Réponse courte: utilisez toujours BigDecimal et assurez-vous que vous utilisez le constructeur avec l' argument String , pas le double.
De retour à votre exemple, le code suivant imprimera 11.4, comme vous le souhaitez.
la source
Découvrez BigDecimal, il gère les problèmes liés à l'arithmétique en virgule flottante comme ça.
Le nouvel appel ressemblerait à ceci:
Utilisez setScale () pour définir le nombre de décimales à utiliser.
la source
Pourquoi ne pas utiliser la méthode round () de la classe Math?
la source
Si vous n'avez pas d'autre choix que d'utiliser des valeurs doubles, vous pouvez utiliser le code ci-dessous.
la source
Ne gaspillez pas vos efforts en utilisant BigDecimal. Dans 99,99999% des cas, vous n'en avez pas besoin. java double type est bien sûr approximatif mais dans presque tous les cas, il est suffisamment précis. Notez que vous avez une erreur au 14e chiffre significatif. C'est vraiment négligeable!
Pour obtenir une bonne sortie, utilisez:
la source