Comment arrondir un nombre à n chiffres après la virgule dans Java
Ce que je voudrais, c'est une méthode pour convertir un double en une chaîne qui arrondit à l'aide de demi-méthode - c'est à dire si la décimale arrondie à 5, on arrondit toujours au prochain numéro. C'est la méthode standard de l'arrondissement la plupart des gens s'attendre dans la plupart des situations.
Je voudrais aussi uniquement de chiffres significatifs pour être affiché à - dire qu'il ne doit pas être tous des zéros à la fin.
Je connais une méthode pour le faire est d'utiliser le String.format
méthode:
String.format("%.5g%n", 0.912385);
retourne:
0.91239
qui est excellent, mais il affiche toujours les nombres avec décimales 5, même si elles ne sont pas significatives:
String.format("%.5g%n", 0.912300);
retourne:
0.91230
Une autre méthode consiste à utiliser le DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
retourne:
0.91238
Cependant, comme vous pouvez le voir, cette utilise des demi-même arrondissement. Qu'en est-il arrondir à la baisse si le chiffre est pair. Ce que j'aimerais c'est ceci:
0.912385 -> 0.91239
0.912300 -> 0.9123
Quelle est la meilleure façon de le réaliser en Java?
Vous devez vous connecter pour publier un commentaire.
Utilisation
setRoundingMode
, définir laRoundingMode
explicitement pour traiter votre problème avec le demi-même round, puis utilisez le modèle de format pour votre sortie requise.Exemple:
donne la sortie:
MODIFIER: l'original de La réponse ne traite pas l'exactitude des valeurs doubles. C'est très bien si vous n'avez pas beaucoup de soins si elle arrondit vers le haut ou vers le bas. Mais si vous voulez précise l'arrondissement, alors vous devez prendre la précision attendue des valeurs en compte. Les valeurs à virgule flottante ont une représentation binaire en interne. Cela signifie qu'une valeur comme 2.77395 n'a pas en fait que la valeur exacte en interne. Il peut être légèrement supérieur ou légèrement plus petit. Si la valeur interne est légèrement plus petit, il ne sera alors pas rond, jusqu'à 2.7740. Pour remédier à cette situation, vous devez être conscient de la précision des valeurs que vous travaillez avec, et d'ajouter ou de soustraire cette valeur avant de l'arrondissement. Par exemple, quand vous savez que vos valeurs sont précises jusqu'à 6 chiffres, puis tour à mi-chemin valeurs, ajouter de l'exactitude de la valeur:
D'arrondir à la baisse, soustrait la précision.
"#.##"
, l'arrondissementHALF_UP
.256.335f
->"256.33"
...(exemple vient de commentaires de @asterite de réponse).DecimalFormat df = new DecimalFormat("0.00"); df.setMaximumFractionDigits(2); df.setRoundingMode(RoundingMode.HALF_UP); df.format(3.775)
retourne 3.77En supposant
value
est undouble
, vous pouvez le faire:C'est pour les 5 chiffres de précision. Le nombre de zéros indiquent le nombre de décimales.
Math.round(0.1 * Math.pow(10,20))/Math.pow(10,20) == 0.09223372036854775
.(double)Math.round(value * 100000) * 0.000001
(double)Math.round(1.005 * 100) / 100 == 1.0
Ne l'utilisez pas!DecimalFormat
pour rendre mon code plus lentement possible: plus le nombre de cycles d'horloge qu'il nécessite, le plus d'argent pour moi 😉265.335
signifie vraiment265.335 += tolerance
, où la tolérance dépend de précédentes opérations et de la plage de valeurs d'entrée. Nous ne connaissons pas la vraie, la valeur exacte. Au bord de valeurs, , soit la réponse est sans doute correct. Si nous en avons besoin pour être exact, nous ne devrions pas travailler en double. Lefail
ici n'est pas de le convertir en double. Son OP pensant qu'il peut compter sur l'entrants265.335
comme étant exactement que.+- tolerance
.(double)
exprimés est nécessaire.HALF_EVEN
arrondi) réponse:x = Math.rint(1000*x); x = Math.rint(x/10.0); return x / 100.0;
. Évidemment, le résultat n'est pas exactement365.34
, mais c'est l'approximation la plus proche et il imprime comme ça.vous obtiendrez un
BigDecimal
. Pour obtenir la chaîne de caractères en dehors de ça, il suffit d'appeler queBigDecimal
'stoString
méthode, ou latoPlainString
méthode pour Java 5+ pour une simple chaîne de format.Exemple de programme:
new BigDecimal(doubleVar)
que vous pouvez rencontrer des problèmes avec l'arrondissement de floating pointsdouble 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
à assurez-vous d'avoir le dernier 0 de.
RoundingMode.
Decimal mode
utiliseRoundingMode.HALF_EVEN.
Comme certains l'ont noté, la réponse correcte est d'utiliser soit
DecimalFormat
ouBigDecimal
. Virgule flottante n'est pas ont décimales de sorte que vous ne peut pas rond/truncate à un certain nombre d'entre eux dans la première place. Vous avez à travailler dans un décimal radix, et c'est ce que ces deux classes.Que j'ai écris le code suivant comme un contre-exemple pour toutes les réponses dans ce fil et, de fait, tous sur StackOverflow (et d'ailleurs) qui recommandent de multiplication suivie par la troncature suivi par la division. Il revient sur les défenseurs de cette technique, pour expliquer pourquoi le code suivant donne la mauvaise sortie dans plus de 92% des cas.
De sortie de ce programme:
EDIT: pour répondre À certains commentaires ci-dessous j'ai refait le module de la partie de la boucle de test à l'aide de
BigDecimal
etnew MathContext(16)
pour le module de l'opération comme suit:Résultat:
((0.25 % 0.01) == 0.0)
prend la valeur false.if ((d % 0.01) != 0.0)
àif (BigDecimal.valueOf(d).compareTo(new BigDecimal(d)) != 0)
, ce qui indique que le taux d'erreur est encore plus élevé qu'initialement prévu (et augmente avec l'échelle, jusqu'à 99.9% pour une échelle de 5)code double d1, d2; d1 = 10.0100000000000000000123D; d2 = 10.0100000D; System.out.println(Math.round(d1 * 100)/100D == d2); // true double d3 = 0.0000090000000000000000000789D; System.out.println(Math.round(d3 * 100)/100D == 0.0D); // true
BTW, je ne préconise pas cette technique. Il est sujet à un débordement possible.100 trials 94 errors
Vous devriez commencer avec un test qui passe, et de montrer que l'introduction de l'arrondissement sauts de le tester.double
que pas d'erreurs ideone.com/BVCHh30.01
ne peut pas être représenté exactement, ce test est mauvais. Un test mieux serait de convertir le résultat deroundOff
àBigDecimal
, et comparer le résultat exact est calculé avecBigDecimal
.BigDecimal/MathContext
avec 16 chiffres de précision pour le module de la partie et j'ai eu 50% d'échecs.a *= temp;
a une imprécision dans l'arrondissement problème de valeurs à proximité d'une frontière. E. g. x.xx5 etposition == 2
. Le produit enregistré dansa
engage un arrondi qui va entraîner le mauvaisroundOff()
valeur de temps à autre. Il aurait fait plus de sens ici à maintenir la une précision supplémentairedouble
aveca = Math.round(a * temp);
plutôt quea *= temp; a = Math.round(a);
Supposons que vous avez
vous pouvez utiliser
BigDecimal
ou sans BigDecimal
avec les deux solutions
d == 9232.13
RoundingMode.HALF_UP
est faux. Essayez avec1.505
. La bonne façon est d'utiliserBigDecimal.valueOf(d)
.HALF_EVEN
mode est connu comme “l'arrondi” souvent utilisé dans les questions financières (d'où le nom). Cette approche est plus juste mathématiquement que la “à l'École arrondissement” généralement enseignée aux enfants. Depuis le 5 se trouve exactement au milieu, toujours arrondi vers le haut ("à l'École") biais des résultats à un plus grand nombre. L'Arrondi coupe la poire en deux, la moitié des valeurs ronde et demi-tour vers le bas (étant donné une distribution aléatoire de valeurs).BigDecimal.valueOf(d)
au lieu denew BigDecimal(d)
si vous voulez éviter les erreurs dues à virgule flottante de l'inexactitude.Vous pouvez utiliser le DecimalFormat classe.
Double.valueOf()
qui a été choisiDouble.parseDouble()
? LevalueOf()
méthode retourne unDouble
objet, alors queparseDouble()
sera de retour d'unedouble
primitive. Avec la façon dont le code est écrit, vous pouvez aussi appliquer de l'auto-unboxing pour le retour de le jeter à la primitive que votretwoDouble
variable attend, un supplément de bytecode de l'opération. Je voudrais changer la réponse à l'utilisationparseDouble()
à la place.Double.parseDouble()
besoinsString
d'entrée.Réel Java de Façon à postes cette solution, qui est aussi compatible pour les versions antérieures à la version 1.6 de Java.
Math.floor(x + 0.5)
etMath.round(x)
@Milhous: le format décimal pour l'arrondi est excellent:
Je voudrais ajouter que cette méthode est très bon à fournir une réelle
numérique, l'arrondissement de mécanisme non seulement visuellement, mais aussi lors du traitement.
Hypothétique: vous avez à mettre en œuvre un arrondissement mécanisme dans une interface graphique
programme. Pour modifier l'exactitude /précision d'un résultat de sortie tout simplement
modifier le signe de format (c'est à dire à l'intérieur des parenthèses). De sorte que:
serait de retour en tant que sortie:
0.912385
serait de retour en tant que sortie:
0.91239
serait de retour en tant que sortie:
0.9124
[EDIT: si le curseur de format, c'est comme si ("#0.############") et vous
entrez un nombre décimal, par exemple 3.1415926, pour la commodité du raisonnement, DecimalFormat
ne produit pas de déchets (par exemple, des zéros à la fin) et sera de retour:
3.1415926
.. si vous êtes de cette façon inclinée. Certes, c'est un peu verbeuxpour le goût de certains dev - mais bon, il a une faible empreinte mémoire
au cours du traitement et est très facile à mettre en œuvre.]
Donc, essentiellement, la beauté de DecimalFormat est simultanément qu'elle gère la chaîne
en apparence, ainsi que le niveau de l'arrondi de précision. Ergo: vous
obtenez deux avantages pour le prix d'un code de mise en œuvre. 😉
double
. Utilisation BigDecimal ou de tout autre decimal-format.Vous pouvez utiliser l'utilitaire suivant la méthode
round(1.005,2);
ouround(0.50594724957626620092, 20);
Voici un résumé de ce que vous pouvez utiliser si vous souhaitez que le résultat comme une Chaîne de caractères:
DecimalFormat#setRoundingMode():
BigDecimal#setScale()
Voici une suggestion de ce que les bibliothèques que vous pouvez utiliser si vous souhaitez
double
comme un résultat. Je ne le recommande pas pour la conversion de chaîne de caractères, même si, comme le double peut ne pas être en mesure de représenter ce que vous voulez exactement (voir, par exemple,ici):Précision de Apache Commons Mathématiques
Fonctions de Colt
Utils de Weka
Un succincte solution:
Voir aussi, https://stackoverflow.com/a/22186845/212950
Grâce à jpdymond offre ce.
Vous pouvez utiliser BigDecimal
Consulter: http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
Essayez ceci: org.apache.commons.math3.util.La précision.round(double x, int échelle)
Voir: http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Apache Commons Bibliothèque de Mathématiques page d'accueil est: http://commons.apache.org/proper/commons-math/index.html
Internes de mise en œuvre de cette méthode est:
Depuis je n'ai pas trouvé de réponse complète sur ce thème, j'ai mis en place une classe qui doit gérer cela correctement, avec le soutien de:
L'utilisation est assez simple:
(Pour les besoins de cet exemple, je suis en utilisant une coutume locale)
Ici est la classe:
Si vous voulez vraiment les nombres décimaux pour le calcul (et non seulement de la production), ne pas utiliser une base binaire format à virgule flottante double.
Je ne l'utilisation de BigDecimal pour les calculs, mais gardez à l'esprit qu'il est dépendant de la taille de
les numéros que vous avez affaire. Dans la plupart de mes réalisations, je trouve l'analyse de double ou
entier Long est suffisant pour un très grand nombre de calculs.
En fait, j'ai
utilisé récemment analysé-à-temps pour obtenir des représentations précises (par opposition à l'hex résultats)
dans une interface graphique, pour des nombres aussi grands que ################################# les personnages (comme un
exemple).
Juste au cas où quelqu'un a encore besoin d'aide avec cela. Cette solution fonctionne parfaitement pour moi.
renvoie une
String
avec la sortie souhaitée.Pour parvenir à cela, nous pouvons utiliser ce formateur:
ou:
Utiliser cette méthode pour obtenir toujours à deux décimales:
La définition de ces valeurs:
À l'aide de la méthode on peut obtenir ces résultats:
démo en ligne.
Je suis d'accord avec la réponse choisie d'utiliser
DecimalFormat
--- ou, alternativement,BigDecimal
.Veuillez lire mise à Jour ci-dessous la première!
Cependant, si vous ne voulez arrondir la valeur de type double et d'obtenir undouble
valeur résultat, vous pouvez utiliserorg.apache.commons.math3.util.Precision.round(..)
comme mentionné ci-dessus. La mise en œuvre utiliseBigDecimal
, est lent et crée des ordures.Un semblable, mais rapide et nettoyage de la méthode, qui est fourni par leDoubleRounder
utilitaire dans le decimal4j bibliothèque:Sortie
Voir
https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
Avertissement: je suis impliqué dans le decimal4j projet.
Mise à jour:
Comme @iaforek souligné DoubleRounder retourne parfois contre-intuitif résultats. La raison en est qu'il effectue mathématiquement l'arrondi correct. Par exemple
DoubleRounder.round(256.025d, 2)
sera arrondi à 256.02 parce que le double de la valeur représentée comme 256.025 d est un peu plus petite que la valeur rationnelle 256.025 et donc sera arrondi vers le bas.Notes:
BigDecimal(double)
constructeur (mais pas àvalueOf(double)
qui utilise la chaîne constructeur).Pour ces raisons, et tout ce qui est mentionné ci-dessus dans ce post, je n'est pas recommandé d'utiliser DoubleRounder.
L'extrait de code ci-dessous montre comment afficher les n chiffres. Le truc, c'est de définir la variable pp pour 1 suivi de n zéros. Dans l'exemple ci-dessous, la variable valeur pp a 5 zéros, donc 5 chiffres seront affichés.
Si vous utilisez
DecimalFormat
pour convertirdouble
àString
, c'est très simple:Il y a plusieurs
RoundingMode
les valeurs de l'enum pour sélectionner à partir, selon le comportement dont vous avez besoin.Je suis venu ici simplement de vouloir une réponse simple sur comment arrondir un nombre. C'est un complément de réponse à fournir.
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. Un
.5
valeur est arrondie. Si vous avez besoin de différentes arrondissement de comportement que cela, vous pouvez utiliser l'une de l'autre Mathématiques fonctions. Voir le comparatif ci-dessous.ronde
Comme indiqué ci-dessus, ce arrondit à l'entier le plus proche.
.5
décimales round up. Cette méthode retourne unint
.ceil
Toute la valeur décimale est arrondie au nombre entier le plus proche. Il va à la ceiling. Cette méthode retourne un
double
.étage
Toute valeur décimale est arrondie au nombre entier le plus proche. Cette méthode retourne un
double
.rint
Ceci est similaire à la ronde que les valeurs décimales arrondir à l'entier le plus proche. Cependant, contrairement à
round
,.5
des valeurs rondes de la même entier. Cette méthode retourne undouble
.Si vous êtes en utilisant une technologie qui a un minimum de JDK. Voici une façon sans Java libs:
DecimalFormat est la meilleure des façons à la sortie, mais je ne préfère pas elle. J'ai toujours le faire tout le temps, parce qu'elle renvoie la valeur de type double. Donc je peux l'utiliser plus que juste sortie.
OU
Si vous avez besoin d'un grand nombre de décimales de la valeur, vous pouvez utiliser BigDecimal à la place. De toute façon
.0
est important. Sans elle, l'arrondissement de 0.33333d5 retour 0.33333 et seulement 9 chiffres permet. La deuxième fonction sans.0
a des problèmes avec 0.30000 retour 0.30000000000000004.voici ma réponse:
Où dp = nombre de décimales que vous souhaitez,
et valeur est un double.
1.0
pourvalue = 1.005
etdp = 2
. Utiliser les this à la place.Gardez à l'esprit que Chaîne de caractères.format() et DecimalFormat produire de la chaîne à l'aide des paramètres Régionaux par défaut. Donc, ils peuvent écrire le nombre formaté avec le point ou la virgule comme séparateur entre les entiers et les décimales. Assurez-vous que l'arrondi de la Chaîne est dans le format que vous souhaitez utiliser java.texte.NumberFormat de la manière suivante:
D'impression paramètres régionaux anglais (peu importe ce que votre locale):
0.99
123.57
123.00
L'exemple pris est Farenda - comment convertir le double Chaîne correctement.
Donc, après la lecture de la plupart des réponses, j'ai réalisé que la plupart d'entre eux ne sera pas précis, en fait, à l'aide de
BigDecimal
semble être le meilleur choix, mais si vous ne comprenez pas comment leRoundingMode
travaux, vous pouvez inévitable de perdre de la précision. J'ai compris cela lorsque l'on travaille avec de gros chiffres dans un projet et pense qu'il peut aider d'autres personnes ayant de la difficulté à l'arrondissement des chiffres. Par exemple.Vous pouvez vous attendre à obtenir
1363.28
de sortie, mais vous allez vous retrouver avec1363.27
, ce qui n'est pas prévu, si vous ne savez pas ce que leRoundingMode
est en train de faire. Donc à la recherche dans le Oracle Docs, vous trouverez la description deRoundingMode.HALF_UP
.Donc, sachant cela, nous avons réalisé que nous ne seront pas obtenir un arrondi exact, si l'on ne veut arrondi vers voisin le plus proche. Donc, pour accomplir adéquat, à la ronde, nous aurions besoin de boucle de la
n-1
décimal vers la décimales souhaité chiffres. Par exemple.Ce sera à la fin de nous donner les résultats attendus, ce qui serait
1363.28
.Si vous Envisagez de 5 ou n le nombre de décimales.
Peut-être cette réponse résoudre votre problème.
Sortie sera: 123.01
cela peut se résoudre avec une boucle et une fonction récursive.
En général, l'arrondi est fait par la mise à l'échelle:
round(num /p) * p
EPSILON
? Ce n'est pas définie dans le code