Nach meiner Erfahrung ist replaceAll (), wie Sie vorgeschlagen haben, der beste Weg, dies zu tun. Es hängt nicht vom aktuellen Gebietsschema ab, es ist einfach und es funktioniert.
Joonas Pulakka
1
@Marco Altieri: Ersetzt replaceAll(",",".")alle Kommas durch Punkte. Wenn es keine Kommas gibt, tut es nichts. Double.valueOf()funktioniert (nur) mit Zeichenfolgen, die Punkt als Dezimaltrennzeichen verwenden. Hier ist nichts vom aktuellen Standardgebietsschema betroffen. docs.oracle.com/javase/8/docs/api/java/lang/…
Joonas Pulakka
4
Das einzige Problem dabei replaceAll(",",".")ist, dass es nur funktioniert, wenn es ein einziges Komma gibt: dh: 1.234.567 wird werfen java.lang.NumberFormatException: multiple points. Eine Regex mit positivem Lookahead wird ausreichen. p.replaceAll(",(?=[0-9]+,)", "").replaceAll(",", ".")Weitere Informationen finden Sie unter
Artemisian
2
Es gibt kein Problem. Die NumberFormatException ist gut. Wie können Sie wissen, welches Komma das richtige ist? Das Format ist falsch und Sie können dem Benutzer lediglich eine besser lesbare Nachricht als die Ausnahme anzeigen.
Der unglaubliche
2
@TheincredibleJan Nein, das Format ist nicht falsch. Einige Gebietsschemas verwenden Komma als Tausendertrennzeichen, sodass Sie mehr als eines davon in einer Zahl haben können und es technisch immer noch eine gültige Eingabe ist.
Dies funktioniert nur, wenn das aktuelle Standardgebietsschema ein Komma als Dezimaltrennzeichen verwendet.
Joonas Pulakka
6
Um die Dinge weiter durcheinander zu bringen, verwenden einige Gebietsschemas Komma als Tausendertrennzeichen . In diesem Fall würde "1.234" auf 1234.0 analysiert, anstatt einen Fehler auszulösen.
Joonas Pulakka
17
Das Problem mit NumberFormat ist, dass ungültige Zeichen stillschweigend ignoriert werden. Wenn Sie also versuchen, "1,23abc" zu analysieren, wird glücklich 1,23 zurückgegeben, ohne dass Sie darauf hingewiesen werden, dass die übergebene Zeichenfolge nicht analysierbare Zeichen enthält. In einigen Situationen könnte das tatsächlich wünschenswert sein, aber ich denke nicht, dass es normalerweise das gewünschte Verhalten ist.
E-Riz
7
Für die Türkei sollten Sie NumberFormat.getInstance (neues Gebietsschema (tr_TR))
Ja ... wenn wir das Trennzeichen für tausend Gruppierungen nicht festlegen und nur das französische Format verwenden, wird eine Zahl im spanischen Format (1.222.222,33) in "1 222 222,33" konvertiert, was ich nicht möchte . So danke!
WesternGun
1
Eine andere Sache ist, dass das spanische Gebietsschema nicht als "Standard" aufgeführt ist und ich keine Localemit korrektem Format erstellen und dann die Zahlenzeichenfolge new Locale("es", "ES")automatisch NumberFormatmit ,als Dezimaltrennzeichen und .als Tausendergruppentrennzeichen DecimalFormat
analysieren kann
Warum sind dort nicht alle Länder verfügbar? Ich finde es komisch, das französische Gebietsschema zum Formatieren polnischer Zahlen zu verwenden ...
Zeile
18
Wie E-Riz hervorhebt, analysiert NumberFormat.parse (String) "1,23abc" als 1,23. Um die gesamte Eingabe zu übernehmen, können wir verwenden:
... ist sehr schnell, da es das zugrunde liegende Zeichenarray char-by-char durchsucht. Die Versionen zum Ersetzen von Zeichenfolgen kompilieren ein RegEx, das ausgewertet werden soll.
Grundsätzlich ist das Ersetzen (char, char) ungefähr zehnmal schneller und da Sie diese Art von Dingen in Low-Level-Code ausführen, ist es sinnvoll, darüber nachzudenken. Der Hot Spot-Optimierer wird es nicht herausfinden ... Auf meinem System sicherlich nicht.
Dies ist die statische Methode, die ich in meinem eigenen Code verwende:
publicstaticdouble sGetDecimalStringAnyLocaleAsDouble (String value){if(value ==null){Log.e("CORE","Null value!");return0.0;}Locale theLocale =Locale.getDefault();NumberFormat numberFormat =DecimalFormat.getInstance(theLocale);Number theNumber;try{
theNumber = numberFormat.parse(value);return theNumber.doubleValue();}catch(ParseException e){// The string value might be either 99.99 or 99,99, depending on Locale.// We can deal with this safely, by forcing to be a point for the decimal separator, and then using Double.valueOf ...//http://stackoverflow.com/questions/4323599/best-way-to-parsedouble-with-comma-as-decimal-separatorString valueWithDot = value.replaceAll(",",".");try{returnDouble.valueOf(valueWithDot);}catch(NumberFormatException e2){// This happens if we're trying (say) to parse a string that isn't a number, as though it were a number!// If this happens, it should only be due to application logic problems.// In this case, the safest thing to do is return 0, having first fired-off a log warning.Log.w("CORE","Warning: Value is not a number"+ value);return0.0;}}}
Was ist, wenn das Standardgebietsschema so etwas wie Deutsch ist, wobei ein Komma eine Dezimalstelle angibt? Sie könnten beispielsweise "1.000.000" übergeben, die nicht in das deutsche Gebietsschema analysiert werden und dann durch "1.000.000" ersetzt werden, was kein gültiges Double ist.
Eddie Curtis
Hallo @jimmycar, ich habe gerade meine Antwort aktualisiert, um die aktuelle Version meiner statischen Methode zu verwenden. Ich hoffe das löst dein Problem! Pete
Pete
1
Sie müssen natürlich das richtige Gebietsschema verwenden. Diese Frage wird helfen.
In dem Fall, in dem Sie das Gebietsschema des empfangenen Zeichenfolgenwerts nicht kennen und es nicht unbedingt dasselbe Gebietsschema wie das aktuelle Standardgebietsschema ist, können Sie Folgendes verwenden:
Es wird ein Double zurückgegeben, unabhängig vom Gebietsschema der Zeichenfolge. Und egal wie viele Kommas oder Punkte es gibt. Das Übergeben 1,000,000.54funktioniert also auch, 1.000.000,54sodass Sie sich beim Parsen der Zeichenfolge nicht mehr auf das Standardgebietsschema verlassen müssen. Der Code ist nicht so optimiert wie er sein kann, daher sind Vorschläge willkommen. Ich habe versucht, die meisten Fälle zu testen, um sicherzustellen, dass das Problem dadurch gelöst wird, aber ich bin nicht sicher, ob es alles abdeckt. Wenn Sie einen Bruchwert finden, lassen Sie es mich wissen.
Die erste Frage lautete : "Gibt es eine bessere Möglichkeit," 1.234 "zu analysieren, um 1.234 zu erhalten, als: p = p.replaceAll (", ",". ");" Wenn Sie der Meinung sind, replacedass sich die Verwendung erheblich von der Verwendung unterscheidet replaceAll, erklären Sie bitte, warum.
replaceAll(",",".")
alle Kommas durch Punkte. Wenn es keine Kommas gibt, tut es nichts.Double.valueOf()
funktioniert (nur) mit Zeichenfolgen, die Punkt als Dezimaltrennzeichen verwenden. Hier ist nichts vom aktuellen Standardgebietsschema betroffen. docs.oracle.com/javase/8/docs/api/java/lang/…replaceAll(",",".")
ist, dass es nur funktioniert, wenn es ein einziges Komma gibt: dh: 1.234.567 wird werfenjava.lang.NumberFormatException: multiple points
. Eine Regex mit positivem Lookahead wird ausreichen.p.replaceAll(",(?=[0-9]+,)", "").replaceAll(",", ".")
Weitere Informationen finden Sie unterAntworten:
Verwenden Sie java.text.NumberFormat :
quelle
Sie können dies verwenden (das französische Gebietsschema hat ein
,
Dezimaltrennzeichen)Oder Sie können
java.text.DecimalFormat
die entsprechenden Symbole verwenden und einstellen:quelle
Locale
mit korrektem Format erstellen und dann die Zahlenzeichenfolgenew Locale("es", "ES")
automatischNumberFormat
mit,
als Dezimaltrennzeichen und.
als TausendergruppentrennzeichenDecimalFormat
Wie E-Riz hervorhebt, analysiert NumberFormat.parse (String) "1,23abc" als 1,23. Um die gesamte Eingabe zu übernehmen, können wir verwenden:
quelle
... ist sehr schnell, da es das zugrunde liegende Zeichenarray char-by-char durchsucht. Die Versionen zum Ersetzen von Zeichenfolgen kompilieren ein RegEx, das ausgewertet werden soll.
Grundsätzlich ist das Ersetzen (char, char) ungefähr zehnmal schneller und da Sie diese Art von Dingen in Low-Level-Code ausführen, ist es sinnvoll, darüber nachzudenken. Der Hot Spot-Optimierer wird es nicht herausfinden ... Auf meinem System sicherlich nicht.
quelle
Wenn Sie das richtige Gebietsschema nicht kennen und die Zeichenfolge tausend Trennzeichen haben kann, kann dies ein letzter Ausweg sein:
Beachten Sie: Dadurch werden Zeichenfolgen wie "R 1 52.43,2" bis "15243.2" gerne analysiert.
quelle
Dies ist die statische Methode, die ich in meinem eigenen Code verwende:
quelle
Sie müssen natürlich das richtige Gebietsschema verwenden. Diese Frage wird helfen.
quelle
In dem Fall, in dem Sie das Gebietsschema des empfangenen Zeichenfolgenwerts nicht kennen und es nicht unbedingt dasselbe Gebietsschema wie das aktuelle Standardgebietsschema ist, können Sie Folgendes verwenden:
Es wird ein Double zurückgegeben, unabhängig vom Gebietsschema der Zeichenfolge. Und egal wie viele Kommas oder Punkte es gibt. Das Übergeben
1,000,000.54
funktioniert also auch,1.000.000,54
sodass Sie sich beim Parsen der Zeichenfolge nicht mehr auf das Standardgebietsschema verlassen müssen. Der Code ist nicht so optimiert wie er sein kann, daher sind Vorschläge willkommen. Ich habe versucht, die meisten Fälle zu testen, um sicherzustellen, dass das Problem dadurch gelöst wird, aber ich bin nicht sicher, ob es alles abdeckt. Wenn Sie einen Bruchwert finden, lassen Sie es mich wissen.quelle
Dies würde den Job machen:
quelle
replace
dass sich die Verwendung erheblich von der Verwendung unterscheidetreplaceAll
, erklären Sie bitte, warum.