64-bitowe podwójne może dokładnie reprezentować liczbę całkowitą +/- 2 53
Biorąc pod uwagę ten fakt, zdecydowałem się użyć podwójnego typu jako jednego typu dla wszystkich moich typów, ponieważ moja największa liczba całkowita jest bez znaku 32-bitowa.
Ale teraz muszę wydrukować te pseudo liczby całkowite, ale problem polega na tym, że są one również pomieszane z rzeczywistymi liczbami podwójnymi.
Jak więc ładnie wydrukować te kopie w Javie?
Próbowałem String.format("%f", value)
, co jest bliskie, ale dostaję dużo zer końcowych dla małych wartości.
Oto przykładowy wynik działania %f
232,00000000 0,18000000000 1237875192.0 4.5800000000 0,00000000 1,23450000
Chcę to:
232 0,18 1237875192 4.58 0 1,2345
Pewnie, że mogę napisać funkcję do przycinania tych zer, ale to duża utrata wydajności z powodu manipulacji ciągiem. Czy mogę zrobić lepiej z innym kodem formatu?
EDYTOWAĆ
Odpowiedzi Toma E. i Jeremy'ego S. są niedopuszczalne, ponieważ obaj arbitralnie zaokrąglają do 2 miejsc po przecinku. Proszę zrozumieć problem przed odpowiedzią.
EDYCJA 2
Pamiętaj, że zależyString.format(format, args...)
to od ustawień regionalnych (patrz odpowiedzi poniżej).
System.out.println("YOUR STRING" + YOUR_DOUBLE_VARIABLE);
Odpowiedzi:
Jeśli chodzi o drukowanie liczb całkowitych przechowywanych jako liczby podwójne, tak jakby były liczbami całkowitymi, a w przeciwnym razie drukowanie liczb podwójnych z minimalną konieczną precyzją:
Produkuje:
I nie polega na manipulacji ciągiem.
źródło
double
większą niż maksymalnaint
. Mimolong
to nadal nie udałoby się to w przypadku ogromnych liczb. Ponadto zwróci ciąg w postaci wykładniczej, np. „1.0E10”, dla dużych wartości, co prawdopodobnie nie jest tym, czego chce pytający. Użyj%f
zamiast%s
w drugim formacie ciągu, aby to naprawić.%f
. Odpowiedź jest specyficzna dla opisanej sytuacji i pożądanego wyniku. OP zasugerował, że ich maksymalna wartość to 32-bitowy znak bez znaku int, który przyjąłem, żeint
jest akceptowalny (niepodpisany, że tak naprawdę nie istnieje w Javie i żaden przykład nie był problematyczny), ale zmianaint
nalong
trywialną poprawkę, jeśli sytuacja jest inna.String.format("%s",d)
??? Mów o niepotrzebnych kosztach ogólnych. ZastosowanieDouble.toString(d)
. Samo dla drugiej:Long.toString((long)d)
.%s
że nie działa z ustawieniami regionalnymi. W języku niemieckim używamy „,” zamiast „.” w liczbach dziesiętnych. Podczas gdyString.format(Locale.GERMAN, "%f", 1.5)
zwraca „1 500 000”,String.format(Locale.GERMAN, "%s", 1.5)
zwraca „1,5” - z „.”, Co w języku niemieckim jest fałszem. Czy istnieje także wersja „% s” zależna od ustawień regionalnych?Jak wskazano w komentarzach, nie jest to odpowiednia odpowiedź na pierwotne pytanie.
To powiedziawszy, jest to bardzo przydatny sposób formatowania liczb bez niepotrzebnych zer końcowych.
źródło
źródło
W skrócie:
Jeśli chcesz pozbyć się zer i problemów z ustawieniami regionalnymi, powinieneś użyć:
Wyjaśnienie:
Dlaczego inne odpowiedzi mi nie pasowały:
Double.toString()
lubSystem.out.println
lubFloatingDecimal.toJavaFormatString
wykorzystuje notacji naukowej, gdy podwójne jest mniejsza niż 10 ^ -3 lub większą niż lub równą 10 ^ 7przy użyciu
%f
domyślna dokładność dziesiętna wynosi 6, w przeciwnym razie możesz ją zakodować na stałe, ale powoduje to dodanie dodatkowych zer, jeśli masz mniej miejsc po przecinku. Przykład:za pomocą
setMaximumFractionDigits(0);
lub%.0f
usuwasz dokładność dziesiętną, co jest dobre dla liczb całkowitych / długich, ale nie dla podwójnejKorzystając z DecimalFormat, jesteś zależny lokalnie. W języku francuskim separatorem dziesiętnym jest przecinek, a nie kropka:
Korzystanie z ustawień regionalnych w języku ANGIELSKIM zapewnia, że otrzymasz punkt separatora dziesiętnego, niezależnie od miejsca działania programu
Po co więc używać 340
setMaximumFractionDigits
?Dwa powody :
setMaximumFractionDigits
akceptuje liczbę całkowitą, ale jej implementacja ma maksymalną dozwoloną liczbę, zDecimalFormat.DOUBLE_FRACTION_DIGITS
czego 340Double.MIN_VALUE = 4.9E-324
więc z 340 cyframi na pewno nie zaokrąglisz swojej podwójnej i luźnej precyzjiźródło
0
zamiast#.
DecimalFormat.DOUBLE_FRACTION_DIGITS
ale używasz wartości 340, którą następnie dodajesz komentarz, aby pokazać, że jest ona równaDecimalFormat.DOUBLE_FRACTION_DIGITS
. Dlaczego po prostu nie użyć stałej ???Dlaczego nie:
Powinno to działać z ekstremalnymi wartościami obsługiwanymi przez Double. Wydajność:
źródło
"%s"
zasadzie dzwoni,d.toString()
ale nie działa zint
lub jeślid==null
!Na moim komputerze następująca funkcja jest około 7 razy szybsza niż funkcja dostarczona przez odpowiedź JasonD , ponieważ unika
String.format
:źródło
Moje 2 centy:
źródło
return String.format(Locale.US, (n % 1 == 0 ? "%.0f" : "%.1f"), n);
.Naw, nieważne.
Utrata wydajności w wyniku manipulacji ciągiem wynosi zero.
A oto kod do przycięcia końca po
%f
źródło
Użyj a
DecimalFormat
isetMinimumFractionDigits(0)
źródło
setMaximumFractionDigits(2)
isetGroupingUsed(false)
(OP nie wspomina o tym, ale z przykładu wydaje się, że jest to wymagane). Ponadto mały przypadek testowy nie boli, ponieważ w tym przypadku jest trywialny. Mimo to, ponieważ uważam, że jest to najprostsze rozwiązanie, głosowanie jest głosowaniem pozytywnym :)źródło
Pamiętaj, że
String.format(format, args...)
jest to zależne od ustawień regionalnych, ponieważ formatuje przy użyciu domyślnych ustawień narodowych użytkownika, to znaczy prawdopodobnie z przecinkami, a nawet spacjami wewnątrz, takimi jak 123 456,789 lub 123 456,789 , co może nie być dokładnie tym, czego oczekujesz.Wolisz używać
String.format((Locale)null, format, args...)
.Na przykład,
odciski
i tak będzie
String.format(format, args...)
w różnych krajach.EDYCJA Ok, ponieważ trwa dyskusja na temat formalności:
źródło
Zrobiłem,
DoubleFormatter
aby efektywnie przekonwertować dużą liczbę podwójnych wartości na ładny / prezentowalny ciąg:Oto kod:
Uwaga: Użyłem 2 funkcji z biblioteki GUAVA. Jeśli nie korzystasz z GUAVA, koduj sam:
źródło
Ten sprawi, że praca będzie dobrze wykonana, wiem, że temat jest stary, ale walczyłem z tym samym problemem, aż do tego doszedłem. Mam nadzieję, że ktoś uzna to za przydatne.
źródło
źródło
źródło
Spóźniona odpowiedź, ale ...
Powiedziałeś, że zdecydowałeś się przechowywać swoje liczby z podwójnym typem . Myślę, że może to być przyczyna problemu, ponieważ zmusza do przechowywania liczb całkowitych w liczbach podwójnych (a zatem utraty początkowej informacji o naturze wartości). Co o zapisywaniu numerów w instancji Number klasy (nadklasa Double i Integer) i poleganie na polimorfizmie w celu ustalenia poprawnego formatu każdej liczby?
Wiem, że refaktoryzacja całej części kodu może być niedopuszczalna z tego powodu, ale może wygenerować pożądany wynik bez dodatkowego kodu / rzutowania / parsowania.
Przykład:
Wytworzy następujące dane wyjściowe:
źródło
Oto co wymyśliłem:
Prosty jeden liner, rzuca tylko int, jeśli naprawdę tego potrzebujesz
źródło
Sformatuj cenę z grupowaniem, zaokrąglaniem, bez zbędnych zer (podwójnie).
Zasady:
2.0000 = 2; 1.0100000 = 1.01
)2.010 = 2.01; 0.20 = 0.2
)1.994 = 1.99; 1.995 = 2; 1.006 = 1.01; 0.0006 -> 0
)0
(null/-0 = 0
)$
(= $56/-$56
)101101.02 = $101,101.02
)Więcej przykładów:
Napisane w Kotlinie jako zabawne rozszerzenie Double (przyczyna używana w Androidzie), ale można je łatwo przekonwertować na Javę, ponieważ zastosowano klasy java.
Jak używać:
Informacje o DecimalFormat : https://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html
źródło
Musiałem skorzystać z tego powodu,
d == (long)d
że naruszyłem raport sonaruźródło
jest to wynik niektórych testów:
źródło
Oto dwa sposoby na osiągnięcie tego. Po pierwsze, krótszy (i prawdopodobnie lepszy) sposób:
A oto dłuższy i prawdopodobnie gorszy sposób:
źródło
W przypadku Kotlin możesz użyć rozszerzenia takiego jak:
źródło
Oto kolejna odpowiedź, która ma opcję dodawania dziesiętnego TYLKO JEŻELI dziesiętna nie była równa zero.
źródło
Oto odpowiedź, która faktycznie działa (kombinacja różnych odpowiedzi tutaj)
źródło
Wiem, że to naprawdę stary wątek. Myślę jednak, że najlepszym sposobem na to jest jak poniżej:
Wynik:
Jedynym problemem jest ostatni problem, w którym 0,0 nie jest usuwany. Ale jeśli jesteś w stanie z tym żyć, to działa najlepiej. % .2f zaokrągli go do ostatnich 2 cyfr dziesiętnych. Podobnie będzie z DecimalFormat. Jeśli potrzebujesz wszystkich miejsc dziesiętnych, ale nie zer końcowych, działa to najlepiej.
źródło
System.out.println(new java.text.DecimalFormat("#.##").format(1.0005));
wydrukuje1
Spowoduje to, że ciąg upuści cyfry 0.
źródło