Un double 64 bits peut représenter un entier +/- 2 53 exactement
Compte tenu de ce fait, je choisis d’utiliser un type double en tant que type unique pour tous mes types, car mon plus grand entier est non signé 32 bits.
Mais maintenant, je dois imprimer ces pseudo entiers, mais le problème est qu’ils sont également mélangés avec des doublons réels.
Alors, comment puis-je imprimer ces doubles bien en Java?
J’ai essayé Ssortingng.format("%f", value)
, qui est proche, sauf que je reçois beaucoup de zéros pour les petites valeurs.
Voici un exemple de sortie de %f
232.00000000 0.18000000000 1237875192.0 4.5800000000 0.00000000 1.23450000
Ce que je veux c’est:
232 0,18 1237875192 4,58 0 1.2345
Bien sûr, je peux écrire une fonction pour réduire ces zéros, mais c’est une perte de performance importante due à la manipulation des chaînes. Puis-je faire mieux avec un autre code de format?
MODIFIER
Les réponses de Tom E. et Jeremy S. sont inacceptables car elles arrondissent arbitrairement à deux décimales. Veuillez comprendre le problème avant de répondre.
EDIT 2
Notez que Ssortingng.format(format, args...)
dépend de la localisation (voir les réponses ci-dessous).
Si l’idée est d’imprimer des entiers stockés en double comme s’ils sont des entiers, et d’imprimer les doublons avec la précision minimale nécessaire:
public static Ssortingng fmt(double d) { if(d == (long) d) return Ssortingng.format("%d",(long)d); else return Ssortingng.format("%s",d); }
Produit:
232 0.18 1237875192 4.58 0 1.2345
Et ne compte pas sur la manipulation de chaînes.
new DecimalFormat("#.##").format(1.199); //"1.2"
Comme indiqué dans les commentaires, ce n’est pas la bonne réponse à la question initiale.
Cela dit, c’est un moyen très utile de formater des nombres sans zéros inutiles.
Ssortingng.format("%.2f", value) ;
En bref:
Si vous voulez vous débarrasser des problèmes de zéros et de parameters régionaux, vous devez utiliser:
double myValue = 0.00000021d; DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); df.setMaximumFractionDigits(340); //340 = DecimalFormat.DOUBLE_FRACTION_DIGITS System.out.println(df.format(myValue)); //output: 0.00000021
Explication:
Pourquoi d’autres réponses ne me convenaient pas:
Double.toSsortingng()
ou System.out.println
ou FloatingDecimal.toJavaFormatSsortingng
utilise des notations scientifiques si double est inférieur à 10 ^ -3 ou supérieur ou égal à 10 ^ 7
double myValue = 0.00000021d; Ssortingng.format("%s", myvalue); //output: 2.1E-7
en utilisant %f
, la précision décimale par défaut est 6, sinon vous pouvez le coder en dur mais cela se traduit par des zéros supplémentaires si vous avez moins de décimales. Exemple :
double myValue = 0.00000021d; Ssortingng.format("%.12f", myvalue); //output: 0.000000210000
en utilisant setMaximumFractionDigits(0);
ou %.0f
vous supprimez toute précision décimale, ce qui est bien pour les entiers / longs mais pas pour le double
double myValue = 0.00000021d; System.out.println(Ssortingng.format("%.0f", myvalue)); //output: 0 DecimalFormat df = new DecimalFormat("0"); System.out.println(df.format(myValue)); //output: 0
En utilisant DecimalFormat, vous êtes dépendant de la région. En français, le séparateur décimal est une virgule, pas un point:
double myValue = 0.00000021d; DecimalFormat df = new DecimalFormat("0"); df.setMaximumFractionDigits(340); System.out.println(df.format(myvalue));//output: 0,00000021
L’utilisation de la langue locale FRANÇAISE vous permet d’obtenir un point pour le séparateur décimal, quel que soit le programme que vous utiliserez.
Pourquoi utiliser 340 alors pour setMaximumFractionDigits
?
Deux raisons :
setMaximumFractionDigits
accepte un entier mais son implémentation a un maximum de chiffres autorisés de DecimalFormat.DOUBLE_FRACTION_DIGITS
qui est égal à 340 Double.MIN_VALUE = 4.9E-324
Ainsi, avec 340 chiffres, vous êtes sûr de ne pas arrondir votre précision double et perdue Pourquoi pas:
if (d % 1.0 != 0) return Ssortingng.format("%s", d); else return Ssortingng.format("%.0f",d);
Cela devrait fonctionner avec les valeurs extrêmes supscopes par Double. Rendements:
0.12 12 12.144252 0
Sur ma machine, la fonction suivante est environ 7 fois plus rapide que la fonction fournie par la réponse de JasonD , car elle évite Ssortingng.format
:
public static Ssortingng prettyPrint(double d) { int i = (int) d; return d == i ? Ssortingng.valueOf(i) : Ssortingng.valueOf(d); }
Mes 2 centimes:
if(n % 1 == 0) { return Ssortingng.format(Locale.US, "%.0f", n)); } else { return Ssortingng.format(Locale.US, "%.1f", n)); }
Naw, ça ne fait rien.
La perte de performance due à la manipulation des chaînes est nulle.
Et voici le code pour couper la fin après %f
private static Ssortingng sortingmTrailingZeros(Ssortingng number) { if(!number.contains(".")) { return number; } return number.replaceAll("\\.?0*$", ""); }
Notez que Ssortingng.format(format, args...)
dépend des parameters régionaux car il met en forme les parameters régionaux par défaut de l’utilisateur, c’est-à-dire avec des virgules et des espaces pairs tels que 123 456 789 ou 123 456 789 . attendre.
Vous pouvez préférer utiliser Ssortingng.format((Locale)null, format, args...)
.
Par exemple,
double f = 123456.789d; System.out.println(Ssortingng.format(Locale.FRANCE,"%f",f)); System.out.println(Ssortingng.format(Locale.GERMANY,"%f",f)); System.out.println(Ssortingng.format(Locale.US,"%f",f));
estampes
123456,789000 123456,789000 123456.789000
et c’est ce que fera Ssortingng.format(format, args...)
dans différents pays.
EDIT Ok, puisqu’il y a eu une discussion sur les formalités:
res += ssortingpFpZeroes(Ssortingng.format((Locale) null, (nDigits!=0 ? "%."+nDigits+"f" : "%f"), value)); ... protected static Ssortingng ssortingpFpZeroes(Ssortingng fpnumber) { int n = fpnumber.indexOf('.'); if (n == -1) { return fpnumber; } if (n < 2) { n = 2; } String s = fpnumber; while (s.length() > n && s.endsWith("0")) { s = s.subssortingng(0, s.length()-1); } return s; }
J’ai créé un DoubleFormatter
pour convertir efficacement un grand nombre de valeurs doubles en une chaîne agréable / présentable:
double horribleNumber = 3598945.141658554548844; DoubleFormatter df = new DoubleFormatter(4,6); //4 = MaxInteger, 6 = MaxDecimal Ssortingng beautyDisplay = df.format(horribleNumber);
Voici le code:
import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.util.Locale; import com.google.common.base.Preconditions; import com.google.common.base.Ssortingngs; /** * Convert a double to a beautiful Ssortingng (US-local): * * double horribleNumber = 3598945.141658554548844; * DoubleFormatter df = new DoubleFormatter(4,6); * Ssortingng beautyDisplay = df.format(horribleNumber); * Ssortingng beautyLabel = df.formatHtml(horribleNumber); * * Manipulate 3 instances of NumberFormat to efficiently format a great number of double values. * (avoid to create an object NumberFormat each call of format()). * * 3 instances of NumberFormat will be reused to format a value v: * * if v < EXP_DOWN, uses nfBelow * if EXP_DOWN <= v <= EXP_UP, uses nfNormal * if EXP_UP < v, uses nfAbove * * nfBelow, nfNormal and nfAbove will be generated base on the precision_ parameter. * * @author: DUONG Phu-Hiep */ public class DoubleFormatter { private static final double EXP_DOWN = 1.e-3; private double EXP_UP; // always = 10^maxInteger private int maxInteger_; private int maxFraction_; private NumberFormat nfBelow_; private NumberFormat nfNormal_; private NumberFormat nfAbove_; private enum NumberFormatKind {Below, Normal, Above} public DoubleFormatter(int maxInteger, int maxFraction){ setPrecision(maxInteger, maxFraction); } public void setPrecision(int maxInteger, int maxFraction){ Preconditions.checkArgument(maxFraction>=0); Preconditions.checkArgument(maxInteger>0 && maxInteger<17); if (maxFraction == maxFraction_ && maxInteger_ == maxInteger) { return; } maxFraction_ = maxFraction; maxInteger_ = maxInteger; EXP_UP = Math.pow(10, maxInteger); nfBelow_ = createNumberFormat(NumberFormatKind.Below); nfNormal_ = createNumberFormat(NumberFormatKind.Normal); nfAbove_ = createNumberFormat(NumberFormatKind.Above); } private NumberFormat createNumberFormat(NumberFormatKind kind) { final String sharpByPrecision = Strings.repeat("#", maxFraction_); //if you do not use Guava library, replace with createSharp(precision); NumberFormat f = NumberFormat.getInstance(Locale.US); //Apply banker's rounding: this is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a sequence of calculations f.setRoundingMode(RoundingMode.HALF_EVEN); if (f instanceof DecimalFormat) { DecimalFormat df = (DecimalFormat) f; DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); //set group separator to space instead of comma //dfs.setGroupingSeparator(' '); //set Exponent symbol to minus 'e' instead of 'E' if (kind == NumberFormatKind.Above) { dfs.setExponentSeparator("e+"); //force to display the positive sign in the exponent part } else { dfs.setExponentSeparator("e"); } df.setDecimalFormatSymbols(dfs); //use exponent format if v is out side of [EXP_DOWN,EXP_UP] if (kind == NumberFormatKind.Normal) { if (maxFraction_ == 0) { df.applyPattern("#,##0"); } else { df.applyPattern("#,##0."+sharpByPrecision); } } else { if (maxFraction_ == 0) { df.applyPattern("0E0"); } else { df.applyPattern("0."+sharpByPrecision+"E0"); } } } return f; } public String format(double v) { if (Double.isNaN(v)) { return "-"; } if (v==0) { return "0"; } final double absv = Math.abs(v); if (absvEXP_UP) { return nfAbove_.format(v); } return nfNormal_.format(v); } /** * format and higlight the important part (integer part & exponent part) */ public Ssortingng formatHtml(double v) { if (Double.isNaN(v)) { return "-"; } return htmlize(format(v)); } /** * This is the base alogrithm: create a instance of NumberFormat for the value, then format it. It should * not be used to format a great numbers of value * * We will never use this methode, it is here only to understanding the Algo principal: * * format v to ssortingng. precision_ is numbers of digits after decimal. * if EXP_DOWN <= abs(v) <= EXP_UP, display the normal format: 124.45678 * otherwise display scientist format with: 1.2345e+30 * * pre-condition: precision >= 1 */ @Deprecated public Ssortingng formatInefficient(double v) { final Ssortingng sharpByPrecision = Ssortingngs.repeat("#", maxFraction_); //if you do not use Guava library, replace with createSharp(precision); final double absv = Math.abs(v); NumberFormat f = NumberFormat.getInstance(Locale.US); //Apply banker's rounding: this is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a sequence of calculations f.setRoundingMode(RoundingMode.HALF_EVEN); if (f instanceof DecimalFormat) { DecimalFormat df = (DecimalFormat) f; DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); //set group separator to space instead of comma dfs.setGroupingSeparator(' '); //set Exponent symbol to minus 'e' instead of 'E' if (absv>EXP_UP) { dfs.setExponentSeparator("e+"); //force to display the positive sign in the exponent part } else { dfs.setExponentSeparator("e"); } df.setDecimalFormatSymbols(dfs); //use exponent format if v is out side of [EXP_DOWN,EXP_UP] if (absvEXP_UP) { df.applyPattern("0."+sharpByPrecision+"E0"); } else { df.applyPattern("#,##0."+sharpByPrecision); } } return f.format(v); } /** * Convert "3.1416e+12" to "3.1416e+12" * It is a html format of a number which highlight the integer and exponent part */ private static Ssortingng htmlize(Ssortingng s) { SsortingngBuilder resu = new SsortingngBuilder(""); int p1 = s.indexOf('.'); if (p1>0) { resu.append(s.subssortingng(0, p1)); resu.append(""); } else { p1 = 0; } int p2 = s.lastIndexOf('e'); if (p2>0) { resu.append(s.subssortingng(p1, p2)); resu.append(""); resu.append(s.subssortingng(p2, s.length())); resu.append(""); } else { resu.append(s.subssortingng(p1, s.length())); if (p1==0){ resu.append(""); } } return resu.toSsortingng(); } }
Remarque: J’ai utilisé 2 fonctions de la bibliothèque GUAVA. Si vous n’utilisez pas GUAVA, codez-le vous-même:
/** * Equivalent to Ssortingngs.repeat("#", n) of the Guava library: */ private static Ssortingng createSharp(int n) { SsortingngBuilder sb = new SsortingngBuilder(); for (int i=0;i
if (d == Math.floor(d)) { return Ssortingng.format("%.0f", d); } else { return Double.toSsortingng(d); }
Ssortingng s = Ssortingng.valueof("your int variable"); while (g.endsWith("0") && g.contains(".")) { g = g.subssortingng(0, g.length() - 1); if (g.endsWith(".")) { g = g.subssortingng(0, g.length() - 1); } }
Celui-ci va bien faire le travail, je sais que le sujet est ancien, mais je me débattais avec le même problème jusqu’à ce que j’y arrive. J’espère que quelqu’un le trouve utile.
public static Ssortingng removeZero(double number) { DecimalFormat format = new DecimalFormat("#.###########"); return format.format(number); }
new DecimalFormat("00.#").format(20.236) //out =20.2 new DecimalFormat("00.#").format(2.236) //out =02.2
Réponse tardive mais …
Vous avez dit que vous choisissez de stocker vos numéros avec le double type . Je pense que cela pourrait être la racine du problème car cela vous oblige à stocker des entiers en doubles (et donc à perdre les informations initiales sur la nature de la valeur). Qu’en est-il de stocker vos numéros dans les instances de la classe Number (superclasse de Double et Integer) et de compter sur le polymorphism pour déterminer le format correct de chaque nombre?
Je sais qu’il n’est peut-être pas acceptable de refactoriser une partie de votre code à cause de cela, mais cela pourrait produire la sortie souhaitée sans code / transtypage / parsing supplémentaire.
Exemple:
import java.util.ArrayList; import java.util.List; public class UseMixedNumbers { public static void main(Ssortingng[] args) { List listNumbers = new ArrayList (); listNumbers.add(232); listNumbers.add(0.18); listNumbers.add(1237875192); listNumbers.add(4.58); listNumbers.add(0); listNumbers.add(1.2345); for (Number number : listNumbers) { System.out.println(number); } } }
Produira la sortie suivante:
232 0.18 1237875192 4.58 0 1.2345
Utilisez un DecimalFormat
et un setMinimumFractionDigits(0)
Voici deux moyens d’y parvenir. Premièrement, la manière la plus courte (et probablement la meilleure):
public static Ssortingng formatFloatToSsortingng(final float f) { final int i=(int)f; if(f==i) return Integer.toSsortingng(i); return Float.toSsortingng(f); }
Et voici la manière la plus longue et probablement la plus mauvaise:
public static Ssortingng formatFloatToSsortingng(final float f) { final Ssortingng s=Float.toSsortingng(f); int dotPos=-1; for(int i=0;i
public static Ssortingng fmt(double d) { Ssortingng val = Double.toSsortingng(d); Ssortingng[] valArray = val.split("\\."); long valLong = 0; if(valArray.length == 2){ valLong = Long.parseLong(valArray[1]); } if (valLong == 0) return Ssortingng.format("%d", (long) d); else return Ssortingng.format("%s", d); }
J’ai dû utiliser cette cause d == (long)d
me donnait violation dans le rapport sonar
C’est ce que j’ai imaginé:
private static Ssortingng format(final double dbl) { return dbl % 1 != 0 ? Ssortingng.valueOf(dbl) : Ssortingng.valueOf((int) dbl); }
Simple liner, ne jette que si besoin de
Voici une réponse qui fonctionne réellement (combinaison de différentes réponses ici)
public static Ssortingng removeTrailingZeros(double f) { if(f == (int)f) { return Ssortingng.format("%d", (int)f); } return Ssortingng.format("%f", f).replaceAll("0*$", ""); }
Je sais que c’est un très vieux sujet. Mais je pense que la meilleure façon de procéder est la suivante:
public class Test { public static void main(Ssortingng args[]){ System.out.println(Ssortingng.format("%s something",new Double(3.456))); System.out.println(Ssortingng.format("%s something",new Double(3.456234523452))); System.out.println(Ssortingng.format("%s something",new Double(3.45))); System.out.println(Ssortingng.format("%s something",new Double(3))); } }
Sortie:
3.456 something 3.456234523452 something 3.45 something 3.0 something
Le seul problème est le dernier où .0 n’est pas supprimé. Mais si vous êtes en mesure de vivre avec cela, cela fonctionne mieux. % .2f l’arrondit aux 2 derniers chiffres décimaux. Donc, DecimalFormat. Si vous avez besoin de toutes les décimales, mais pas des zéros, cela fonctionne mieux.
Ssortingng s = "1.210000"; while (s.endsWith("0")){ s = (s.subssortingng(0, s.length() - 1)); }
Cela fera la chaîne de laisser tomber le 0-s tailing.