Ich möchte folgende Zahlen mit Java in die Zahlen daneben formatieren:
1000 to 1k
5821 to 5.8k
10500 to 10k
101800 to 101k
2000000 to 2m
7800000 to 7.8m
92150000 to 92m
123200000 to 123m
Die Zahl rechts ist lang oder ganzzahlig, die Zahl links ist Zeichenfolge. Wie soll ich das angehen? Ich habe bereits wenig Algorithmus dafür gemacht, aber ich dachte, es gibt vielleicht schon etwas, das besser funktioniert und keine zusätzlichen Tests erfordert, wenn ich anfange, mich mit Milliarden und Billionen zu beschäftigen :)
Zusätzliche Anforderungen:
- Das Format sollte maximal 4 Zeichen enthalten
- Das obige bedeutet, dass 1.1k in Ordnung ist. 11.2k ist nicht in Ordnung. Gleiches gilt für 7,8 m ist 19,1 m nicht. Nur eine Ziffer vor dem Dezimalpunkt darf einen Dezimalpunkt haben. Zwei Ziffern vor dem Dezimalpunkt bedeuten, dass keine Ziffern nach dem Dezimalpunkt stehen.
- Es ist keine Rundung erforderlich. (Zahlen, die mit k und m als Anhang angezeigt werden, sind eher analoge Anzeigen, die auf einen nicht präzisen logischen Artikel hinweisen. Daher ist die Rundung hauptsächlich aufgrund der Art der Variablen irrelevant, da sie mehrere Stellen erhöhen oder verordnen kann, selbst wenn Sie das zwischengespeicherte Ergebnis betrachten.)
java
number-formatting
Mat B.
quelle
quelle
No rounding is necessary
scheint mir absurd. Ist es nur um die Dinge zu komplizieren? Wäre es nicht besser, dies umzuformulierenRounding is not necessary, but welcome
?Antworten:
Hier ist eine Lösung, die für jeden langen Wert funktioniert und die ich gut lesbar finde (die Kernlogik wird in den unteren drei Zeilen der
format
Methode ausgeführt).Es nutzt
TreeMap
, um das passende Suffix zu finden. Es ist überraschend effizienter als eine frühere Lösung, die Arrays verwendet und schwieriger zu lesen ist.Testcode
quelle
-5821
sollte als-5k
, nicht als formatiert sein-5.8k
.-
dem Präfix , um die gleiche Anzahl signifikanter Ziffern beizubehalten. Es gibt andere Möglichkeiten ...Ich weiß, das sieht eher aus wie ein C-Programm, ist aber superleicht!
Es gibt aus:
quelle
Hier eine Lösung, die die technische Notation von DecimalFormat verwendet:
Ausgabe:
quelle
Brauchen Sie etwas Verbesserung, aber: StrictMath zur Rettung!
Sie können das Suffix in einen String oder ein Array einfügen und sie basierend auf der Leistung oder ähnlichem abrufen.
Die Aufteilung kann auch um die Leistung herum verwaltet werden, ich denke, fast alles dreht sich um den Leistungswert. Ich hoffe es hilft!
Ausgänge:
quelle
Probleme mit aktuellen Antworten
Java-Lösung
Diese Lösung (eine Erweiterung dieser Antwort ) behebt die oben genannten Probleme.
Groovige Lösung
Die Lösung wurde ursprünglich in Groovy geschrieben, wie unten gezeigt.
Tests (Groovy)
Die Tests sind in Groovy geschrieben, können jedoch verwendet werden, um entweder die Java- oder die Groovy-Klasse zu überprüfen (da beide denselben Namen und dieselbe API haben).
quelle
Die ICU-Bibliothek verfügt über einen regelbasierten Formatierer für Zahlen, der für die Rechtschreibung von Zahlen usw. verwendet werden kann. Ich denke, die Verwendung der ICU würde Ihnen eine lesbare und wartbare Lösung bieten.
[Verwendung]
Die richtige Klasse ist RuleBasedNumberFormat. Das Format selbst kann als separate Datei (oder als String-Konstante IIRC) gespeichert werden.
Beispiel von http://userguide.icu-project.org/formatparse/numbers
Die gleiche Seite zeigt römische Ziffern, also denke ich, dass Ihr Fall auch möglich sein sollte.
quelle
CompactDecimalFormat
. API Level 24+Mit Java-12 + können Sie
NumberFormat.getCompactNumberInstance
die Zahlen formatieren. Sie können eineNumberFormat
erste als erstellenund dann verwenden Sie es, um
format
:quelle
Wichtig: Antworten des Gießens
double
wird für Zahlen nicht wie99999999999999999L
und zurück100P
statt ,99P
weildouble
Anwendungen derIEEE
Standard :Diese Lösung schneidet unerwünschte Ziffern ab und funktioniert für alle
long
Werte . Einfache aber performante Implementierung (Vergleich unten). -120k kann nicht mit 4 Zeichen ausgedrückt werden, selbst -0,1M ist zu lang. Deshalb müssen für negative Zahlen 5 Zeichen in Ordnung sein:Der Test
else if
am Anfang ist notwendig, da das Min-(2^63)
und das Max ist(2^63)-1
und daher die Zuordnungnumber = -number
fehlschlagen würde, wennnumber == Long.MIN_VALUE
. Wenn wir eine Überprüfung durchführen müssen, können wir auch so viele Zahlen wie möglich einfügen, anstatt nur nach zu suchennumber == Long.MIN_VALUE
.Der Vergleich dieser Implementierung mit derjenigen, die die meisten Upvotes erhalten hat (derzeit die schnellste), hat gezeigt, dass sie mehr als fünfmal schneller ist (dies hängt von den Testeinstellungen ab, aber mit mehr Zahlen wird der Gewinn größer und diese Implementierung hat mehr Überprüfungen durchführen, da alle Fälle behandelt werden. Wenn also der andere behoben würde, würde der Unterschied noch größer werden. Es ist so schnell, weil es keine Gleitkommaoperationen, keinen Logarithmus, keine Leistung, keine Rekursion, keinen regulären Ausdruck, keine ausgeklügelten Formatierer und keine Minimierung der Anzahl der erstellten Objekte gibt.
Hier ist das Testprogramm:
Mögliche Ausgabe:
2309 vs. 11591
(ungefähr gleich, wenn nur positive Zahlen verwendet werden und viel extremer, wenn die Ausführungsreihenfolge umgekehrt wird, hat dies möglicherweise etwas mit der Speicherbereinigung zu tun)quelle
Hier ist eine kurze Implementierung ohne Rekursion und nur eine sehr kleine Schleife. Funktioniert nicht mit negativen Zahlen, unterstützt aber alle positiven
long
s bis zuLong.MAX_VALUE
:Ausgänge:
Ich habe auch ein wirklich einfaches Benchmarking durchgeführt (Formatieren von 10 Millionen zufälligen Longs) und es ist erheblich schneller als die Implementierung von Elijah und etwas schneller als die Implementierung von Assylias.
quelle
Für alle, die abrunden wollen. Dies ist eine großartige, einfach zu lesende Lösung, die die Java.Lang.Math-Bibliothek nutzt
quelle
Der folgende Code zeigt, wie Sie dies mit Blick auf eine einfache Erweiterung tun können.
Die "Magie" liegt hauptsächlich in der
makeDecimal
Funktion, die für die korrekten Werte garantiert, dass Sie nie mehr als vier Zeichen in der Ausgabe haben.Es extrahiert zuerst den gesamten und den zehnten Teil für einen gegebenen Divisor, so dass beispielsweise
12,345,678
mit einem Divisor von1,000,000
einwhole
Wert von12
und eintenths
Wert von erhalten wird3
.Daraus kann er anhand der folgenden Regeln entscheiden, ob nur der gesamte Teil oder sowohl der gesamte als auch der zehnte Teil ausgegeben wird:
Der Code dafür lautet:
Dann ist es einfach, diese Hilfsfunktion mit den richtigen Werten aufzurufen, einschließlich einiger Konstanten, um dem Entwickler das Leben zu erleichtern:
Die Tatsache, dass die
makeDecimal
Funktion die Grunzarbeit erledigt, bedeutet, dass das Erweitern darüber hinaus999,999,999
nur eine Frage des Hinzufügens einer zusätzlichen Zeile istXlat
, so einfach, dass ich es für Sie getan habe.Das Finale
return
inXlat
benötigt keine Bedingung, da der größte Wert, den Sie in einem 64-Bit-Long mit Vorzeichen halten können, nur etwa 9,2 Billionen beträgt.Aber wenn Oracle aufgrund einer bizarren Anforderung beschließt, einen 128-Bit-
longer
Typ oder einen 1024-Bit-damn_long
Typ hinzuzufügen , sind Sie bereit dafür :-)Und schließlich ein kleines Testgeschirr, mit dem Sie die Funktionalität überprüfen können.
Sie können an der Ausgabe erkennen, dass Sie das bekommen, was Sie brauchen:
quelle
Ich weiß nicht, ob es der beste Ansatz ist, aber das habe ich getan.
--- Code ---
quelle
Meine Funktion zum Konvertieren großer Zahlen in kleine Zahlen (mit 2 Ziffern). Sie können die Anzahl der Ziffern durch Ändern
#.##
in ändernDecimalFormat
Testen
Hoffe es hilft
quelle
Mein Java ist rostig, aber so würde ich es in C # implementieren:
Es wäre einfach, dies anzupassen, um CS-Kilo (1.024) anstelle von metrischen Kilo zu verwenden oder um weitere Einheiten hinzuzufügen. Es formatiert 1.000 als "1.0 k" anstatt als "1 k", aber ich vertraue darauf, dass dies unerheblich ist.
Um die spezifischere Anforderung "nicht mehr als vier Zeichen" zu erfüllen, entfernen Sie die Leerzeichen vor den Suffixen und passen Sie den mittleren Block wie folgt an:
quelle
ToString
Methode in Java nicht - Sie benötigen ein NumberFormat, das andere Probleme verursachen kann (Gebietsschemasensitiv usw.).Mein Favorit. Sie können auch "k" usw. als Indikator für die Dezimalzahl verwenden, wie dies im elektronischen Bereich üblich ist. Dadurch erhalten Sie eine zusätzliche Ziffer ohne zusätzlichen Platz
In der zweiten Spalte wird versucht, so viele Ziffern wie möglich zu verwenden
Dies ist der Code
quelle
Um meinem Kommentar treu zu bleiben, dass ich die Lesbarkeit über die Leistung stellen würde, ist hier eine Version, in der klar sein sollte, was passiert (vorausgesetzt, Sie haben
BigDecimal
s zuvor verwendet), ohne übermäßige Kommentare abzugeben (ich glaube an selbstdokumentierenden Code), ohne sich um die Leistung zu sorgen (Da ich mir kein Szenario vorstellen kann, in dem Sie dies so viele Millionen Mal tun möchten, dass die Leistung sogar in Betracht gezogen wird).Diese Version:
BigDecimal
s zur Präzision und zur Vermeidung von RundungsproblemenHALF_UP
wie in den TestsREQUIRED_PRECISION
)enum
, um die Schwellenwerte zu definieren, dh kann leicht angepasst werden, um KB / MB / GB / TB anstelle von k / m / b / t usw. zu verwenden, und kann natürlich bei Bedarf darüber hinaus erweitertTRILLION
werdenThreshold.java :
NumberShortener.java :
(Kommentieren Sie die
println
Anweisungen aus oder ändern Sie sie, um Ihren bevorzugten Logger zu verwenden, um zu sehen, was er tut.)Und schließlich die Tests in NumberShortenerTest (Plain JUnit 4):
Fühlen Sie sich frei, in den Kommentaren darauf hinzuweisen, wenn ich einen signifikanten Testfall verpasst habe oder wenn die erwarteten Werte angepasst werden sollten.
quelle
TreeMap
Ansatz. "Lesbarkeit" ist natürlich subjektiv. ;-) Was ist nun, wenn jemand anders runden möchte als in deiner Version abschneiden? (Wenn Sie dies beispielsweise verwenden, um die Dateigröße anzugeben, wer möchte dann abschneiden?) Wenn Sie Potenzen von 2 statt 10 möchten? Sie müssten ein gutes Stück umschreiben, nicht wahr? Wie gesagt, ich habe absichtlich nicht versucht, meinen Code zu spielen, von dem ein Großteil hätte verkürzt werden können (ich würde zum Beispiel niemals ein Wenn-Dann in einer Zeile behalten).Das ist mein Code. sauber und einfach.
quelle
Hinzufügen meiner eigenen Antwort, Java-Code, selbsterklärenden Code ..
quelle
Dieses Code-Snippet ist einfach tödlich einfach und sauber und funktioniert vollständig:
quelle
Versuche dies :
quelle
Ausgabe:
quelle
quelle