Ce que je voudrais, c'est une méthode pour convertir un double en une chaîne qui arrondit en utilisant la méthode de la moitié - c'est-à-dire que si la décimale à arrondir est 5, elle arrondit toujours au nombre suivant. Il s'agit de la méthode standard d'arrondi que la plupart des gens attendent dans la plupart des situations.
Je voudrais également que seuls les chiffres significatifs soient affichés - c'est-à-dire qu'il ne devrait pas y avoir de zéros à la fin.
Je sais qu'une méthode pour ce faire est d'utiliser la String.format
méthode:
String.format("%.5g%n", 0.912385);
Retour:
0.91239
ce qui est génial, mais il affiche toujours des nombres avec 5 décimales même s'ils ne sont pas significatifs:
String.format("%.5g%n", 0.912300);
Retour:
0.91230
Une autre méthode consiste à utiliser DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
Retour:
0.91238
Cependant, comme vous pouvez le voir, cela utilise un arrondi demi-pair. Autrement dit, il arrondira vers le bas si le chiffre précédent est pair. Ce que j'aimerais, c'est ceci:
0.912385 -> 0.91239
0.912300 -> 0.9123
Quelle est la meilleure façon d'y parvenir en Java?
"#.##"
:, arrondiHALF_UP
.256.335f
->"256.33"
... (l'exemple provient des commentaires de la réponse de @ asterite).En supposant que
value
c'est undouble
, vous pouvez faire:C'est pour une précision à 5 chiffres. Le nombre de zéros indique le nombre de décimales.
la source
Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775
.265.335
signifie vraiment265.335 += tolerance
, où la tolérance dépend des opérations précédentes et de la plage de valeurs d'entrée. Nous ne connaissons pas la vraie valeur exacte. Aux valeurs de bord, l'une ou l'autre réponse est sans doute correcte. Si nous devons être exacts, nous ne devons pas travailler en double. L'fail
ici n'est pas de reconvertir en double. C'est en pensant OP qu'il peut compter sur l'arrivée265.335
comme étant exactement cela.vous obtiendrez un
BigDecimal
. Pour obtenir la chaîne hors de lui, il suffit d' appeler queBigDecimal
de »toString
la méthode, outoPlainString
méthode pour Java 5+ pour une chaîne de format ordinaire.Exemple de programme:
la source
new BigDecimal(doubleVar)
car vous pouvez rencontrer des problèmes avec l'arrondi des points flottantsdouble val = 265.335;
,BigDecimal.valueOf(val).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.34
, mais(new BigDecimal(val)).setScale(decimals, BigDecimal.ROUND_HALF_UP).toPlainString();
=>265.33
.Vous pouvez également utiliser le
pour vous assurer que vous avez les 0 de fin.
la source
RoundingMode.
Decimal mode
utiliseRoundingMode.HALF_EVEN.
Comme certains l'ont noté, la bonne réponse consiste à utiliser soit
DecimalFormat
ouBigDecimal
. Les virgules flottantes n'ont pas de décimales, vous ne pouvez donc pas arrondir / tronquer à un nombre spécifique d'entre elles en premier lieu. Vous devez travailler dans une base décimale, et c'est ce que font ces deux classes.Je poste le code suivant comme contre-exemple à toutes les réponses dans ce fil et en effet partout dans StackOverflow (et ailleurs) qui recommandent la multiplication suivie de la troncature suivie de la division. Il incombe aux partisans de cette technique d'expliquer pourquoi le code suivant produit la mauvaise sortie dans plus de 92% des cas.
Résultat de ce programme:
EDIT: Pour répondre à certains commentaires ci-dessous, j'ai refait la partie module de la boucle de test en utilisant
BigDecimal
etnew MathContext(16)
pour l'opération de module comme suit:Résultat:
la source
100 trials 94 errors
Vous devriez commencer par un test qui réussit et montrer que l'introduction de l'arrondi rompt le test.double
pas d'erreurs ideone.com/BVCHh3Supposons que vous ayez
vous pouvez utiliser
BigDecimal
ou sans BigDecimal
avec les deux solutions
d == 9232.13
la source
RoundingMode.HALF_UP
est fausse. Essayez-le avec1.505
. La bonne façon est d'utiliserBigDecimal.valueOf(d)
.Vous pouvez utiliser la classe DecimalFormat.
la source
Double.valueOf()
été choisiDouble.parseDouble()
? LavalueOf()
méthode renvoie unDouble
objet, tandis queparseDouble()
renvoie unedouble
primitive. Avec la façon dont le code actuel est écrit, vous appliquez également la décompression automatique au retour pour le convertir en la primitive attendue par votretwoDouble
variable, une opération de bytecode supplémentaire. Je changerais la réponse à utiliser à laparseDouble()
place.Double.parseDouble()
a besoin deString
commentaires.Java's Real-How publie cette solution, qui est également compatible avec les versions antérieures à Java 1.6.
la source
la source
Math.floor(x + 0.5)
etMath.round(x)
@Milhous: le format décimal pour l'arrondi est excellent:
J'ajouterais que cette méthode est très efficace pour fournir un véritable mécanisme d'arrondi numérique - non seulement visuellement, mais aussi lors du traitement.
Hypothèse: vous devez implémenter un mécanisme d'arrondi dans un programme GUI. Pour modifier l'exactitude / la précision d'une sortie de résultat, il suffit de changer le format du curseur (c'est-à-dire entre crochets). Pour que:
retournerait en sortie:
0.912385
retournerait en sortie:
0.91239
retournerait en sortie:
0.9124
[EDIT: aussi si le format caret est comme ça ("# 0. ############") et que vous entrez une décimale, par exemple 3.1415926, pour les besoins de l'argument, DecimalFormat ne produit aucune ordure ( par exemple des zéros à la fin) et retournera:
3.1415926
.. si vous êtes incliné de cette façon. Certes, c'est un peu bavard au goût de certains développeurs - mais bon, il a une faible empreinte mémoire pendant le traitement et est très facile à implémenter.]Donc, essentiellement, la beauté de DecimalFormat est qu'il gère simultanément l'apparence de la chaîne - ainsi que le niveau de précision d'arrondi défini. Ergo: vous bénéficiez de deux avantages pour le prix d'une seule implémentation de code. ;)
la source
double
. Utilisez BigDecimal ou tout autre format décimal.Voici un résumé de ce que vous pouvez utiliser si vous voulez que le résultat soit une chaîne:
DecimalFormat # setRoundingMode () :
BigDecimal # setScale ()
Voici une suggestion des bibliothèques que vous pouvez utiliser si vous le souhaitez
double
. Cependant, je ne le recommanderais pas pour la conversion de chaînes, car double peut ne pas être en mesure de représenter exactement ce que vous voulez (voir par exemple ici ):Précision d'Apache Commons Math
Fonctions de Colt
Ustensiles de Weka
la source
Vous pouvez utiliser la méthode utilitaire suivante:
la source
round(1.005,2);
ouround(0.50594724957626620092, 20);
Une solution succincte:
Voir aussi, https://stackoverflow.com/a/22186845/212950 Merci à jpdymond de nous l' avoir proposé.
la source
Vous pouvez utiliser BigDecimal
Référez-vous à: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
la source
Essayez ceci: org.apache.commons.math3.util.Precision.round (double x, échelle int)
Voir: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
La page d'accueil de la bibliothèque de mathématiques Apache Commons est la suivante : http://commons.apache.org/proper/commons-math/index.html
L'implémentation interne de cette méthode est:
la source
Depuis que je n'ai trouvé aucune réponse complète sur ce thème, j'ai mis en place une classe qui devrait gérer cela correctement, avec le support de:
L'utilisation est assez simple :
(Pour cet exemple, j'utilise un environnement local personnalisé)
Voici la classe :
la source
Si vous voulez vraiment des nombres décimaux pour le calcul (et pas seulement pour la sortie), n'utilisez pas un format à virgule flottante binaire comme double.
J'utilise BigDecimal pour les calculs, mais gardez à l'esprit que cela dépend de la taille des nombres avec lesquels vous avez affaire. Dans la plupart de mes implémentations, je trouve que l'analyse du double ou de l'entier à Long est suffisante pour les calculs de très grand nombre.
En fait, j'ai récemment utilisé l'analyse syntaxique pour obtenir des représentations précises (par opposition aux résultats hexadécimaux) dans une interface graphique pour des nombres aussi grands que ################### ############### caractères (à titre d'exemple).
la source
Pour ce faire, nous pouvons utiliser ce formateur:
ou:
Utilisez cette méthode pour obtenir toujours deux décimales:
Définition de ces valeurs:
En utilisant la méthode, nous pouvons obtenir ces résultats:
démo en ligne.
la source
Juste au cas où quelqu'un aurait encore besoin d'aide. Cette solution fonctionne parfaitement pour moi.
renvoie un
String
avec la sortie souhaitée.la source
Je suis d'accord avec la réponse choisie à utiliser
DecimalFormat
--- ou alternativementBigDecimal
.Veuillez d'abord lire la mise à jour ci-dessous!
Toutefois , si vous ne voulez arrondir la valeur double et d' obtenir undouble
résultat de valeur, vous pouvez utiliserorg.apache.commons.math3.util.Precision.round(..)
comme mentionné ci - dessus. L'implémentation utiliseBigDecimal
, est lente et crée des ordures.Une méthode similaire mais rapide et sans déchets est fournie par l'DoubleRounder
utilitaire dans la bibliothèque decimal4j:Sortira
Voir https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Avertissement: je suis impliqué dans le projet decimal4j.
Mise à jour: Comme l'a souligné @iaforek, DoubleRounder renvoie parfois des résultats contre-intuitifs. La raison en est qu'il effectue un arrondi mathématiquement correct. Par exemple,
DoubleRounder.round(256.025d, 2)
il sera arrondi à 256,02 car la valeur double représentée par 256,025d est quelque peu inférieure à la valeur rationnelle 256,025 et sera donc arrondie à la baisse.Remarques:
BigDecimal(double)
constructeur (mais pas à celuivalueOf(double)
qui utilise le constructeur de chaîne).Pour ces raisons et tout ce qui est mentionné ci-dessus dans ce post, je ne peux pas recommander d'utiliser DoubleRounder .
la source
L'extrait de code ci-dessous montre comment afficher n chiffres. L'astuce consiste à définir la variable pp à 1 suivi de n zéros. Dans l'exemple ci-dessous, la valeur pp variable a 5 zéros, donc 5 chiffres seront affichés.
la source
Si vous utilisez
DecimalFormat
pour convertirdouble
enString
, c'est très simple:Il existe plusieurs
RoundingMode
valeurs d'énumération à sélectionner, selon le comportement dont vous avez besoin.la source
Je suis venu ici juste pour avoir une réponse simple sur la façon d'arrondir un nombre. Ceci est une réponse supplémentaire pour fournir cela.
Comment arrondir un nombre en Java
Le cas le plus courant est d'utiliser
Math.round()
.Les nombres sont arrondis au nombre entier le plus proche. Une
.5
valeur est arrondie. Si vous avez besoin d'un comportement d'arrondi différent de celui-là, vous pouvez utiliser l'une des autres fonctions mathématiques . Voir la comparaison ci-dessous.rond
Comme indiqué ci-dessus, cela arrondit au nombre entier le plus proche.
.5
décimales arrondies. Cette méthode renvoie unint
.plafond
Toute valeur décimale est arrondie au nombre entier suivant. Cela va jusqu'au plafond . Cette méthode renvoie un
double
.sol
Toute valeur décimale est arrondie à l'entier suivant. Cette méthode renvoie un
double
.rint
Ceci est similaire à arrondir dans la mesure où les valeurs décimales sont arrondies à l'entier le plus proche. Cependant, à la différence
round
,.5
autour de valeurs à l'entier même. Cette méthode renvoie undouble
.la source
Si vous utilisez une technologie qui a un JDK minimal. Voici un moyen sans aucune bibliothèque Java:
la source
DecimalFormat est le meilleur moyen de sortie, mais je ne le préfère pas. Je le fais toujours tout le temps, car il renvoie la double valeur. Je peux donc l'utiliser plus qu'une simple sortie.
OU
Si vous avez besoin d'une valeur décimale élevée, vous pouvez utiliser BigDecimal à la place. Quoi qu'il en soit,
.0
c'est important. Sans elle, l'arrondi de 0,33333d5 renvoie 0,33333 et seuls 9 chiffres sont autorisés. La deuxième fonction sans.0
a des problèmes avec 0.30000 return 0.30000000000000004.la source
voici ma réponse:
la source
Donc, après avoir lu la plupart des réponses, j'ai réalisé que la plupart d'entre elles ne seraient pas précises, en fait, l'utilisation
BigDecimal
semble être le meilleur choix, mais si vous ne comprenez pas comment celaRoundingMode
fonctionne, vous perdrez inévitablement la précision. J'ai compris cela lorsque je travaillais avec de grands nombres dans un projet et pensais que cela pourrait aider d'autres personnes à avoir du mal à arrondir les nombres. Par exemple.Vous vous attendriez à obtenir
1363.28
une sortie, mais vous vous retrouverez avec1363.27
, ce qui n'est pas prévu, si vous ne savez pas ce queRoundingMode
fait. En consultant les documents Oracle , vous trouverez la description suivante pourRoundingMode.HALF_UP
.Donc, sachant cela, nous avons réalisé que nous n'obtiendrons pas un arrondi exact, sauf si nous voulons arrondir vers le plus proche voisin . Ainsi, pour accomplir un tour adéquat, nous aurions besoin de boucler de la
n-1
décimale vers les chiffres décimaux souhaités. Par exemple.Cela finira par nous donner la sortie attendue, ce qui serait le cas
1363.28
.la source
Où dp = décimale que vous voulez, et la valeur est un double.
la source
1.0
pourvalue = 1.005
etdp = 2
. Utilisez -le à la place.Gardez à l'esprit que String.format () et DecimalFormat produisent une chaîne en utilisant les paramètres régionaux par défaut. Ils peuvent donc écrire un nombre formaté avec un point ou une virgule comme séparateur entre les parties entières et décimales. Pour vous assurer que la chaîne arrondie est au format souhaité, utilisez java.text.NumberFormat comme suit:
S'imprimera dans les paramètres régionaux anglais (quel que soit votre paramètre régional): 0.99 123.57 123.00
L'exemple est tiré de Farenda - comment convertir correctement le double en String .
la source
En général, l'arrondi se fait par mise à l'échelle:
round(num / p) * p
la source