2012-01-05 8 views
9

Wiem, jak sformatować podwójne, aby zachować tylko dostępne miejsca dziesiętne (DP), do pewnej liczby DP. Ten przykład zawiera do 4 DP.Formatuj dwukrotnie, aby pominąć niepotrzebne ".0" i nigdy nie zaokrąglaj.

double d = 1.0; 
    DecimalFormat df = new DecimalFormat("#.####"); 
    System.out.print(df.format(d)); // returns "1" 

    double d = 1.23; 
    DecimalFormat df = new DecimalFormat("#.####"); 
    System.out.print(df.format(d)); // returns "1.23" 

    double d = 1.2345678; 
    DecimalFormat df = new DecimalFormat("#.####"); 
    System.out.print(df.format(d)); // returns "1.2346", rounding off: bad! 

Teraz chcę liczby całkowite, np. 1.0 do zwrócenia "1" bez niepotrzebnego .0, a znak formatu # zapewnia tę funkcjonalność. Ale jak mogę się upewnić, że liczba ta nigdy się nie kończy? Czy istnieje inny sposób niż arbitralnie długi łańcuch #, taki jak "#.###########################################"?

czy mam po prostu użyć domyślnej konwersji do podwójnego sznurka i obciąć ".0" jeżeli okaże się na końcu:

String s = "" + d; 
    if(s.substring(s.length()-2).equals(".0")) { 
     s=s.substring(0, s.length()-2); 
    } 

Oba sposoby Wygląda strasznie niezdarny.

Odpowiedz

14

używam następujących

double d = 
String s = (long) d == d ? "" + (long) d : "" + d; 

jeśli trzeba Dwuosobowy zamiast za podwójne. (Osobiście wolałbym uniknąć stosując opakowanie, jeśli można)

Double d = 
String s = d.longValue() == d ? "" + d.longValue() : "" + d; 
+0

+1 dla Wow ... !! – RanRag

+2

, nawet jeśli kompilator może zoptymalizować go, uważam, że lepszym stylem będzie użycie String.valueOf (x) zamiast "" + x – rurouni

+0

@rurouni Wielu zgodziłoby się z tobą. Preferuję jednak prostszy kod, ponieważ jest on szybszy do odczytu i zapisu, co pozwala zaoszczędzić czas. Jeśli wydajność jest problemem, nadal nie użyłbym valueOf podczas tworzenia obiektów. –

-1

Można użyć Double.doubleToLongBits() i wyodrębnić wykładnik i mantysy. Od api Doc:

Bit 63 (bit, który jest wybrany przez maskę 0x8000000000000000L) reprezentuje znak liczby zmiennoprzecinkowej. Bity 62-52 (bity wybrane przez maskę 0x7ff0000000000000L) reprezentują wykładnik . Bity 51-0 (bity wybrane przez maskę 0x000fffffffffffffL) reprezentują significand (czasami nazywane mantysą ) liczby zmiennoprzecinkowej.

Wykładnik może być wykorzystane do określenia liczby cyfr znaczących, ale zawsze trzeba zaokrąglić w pewnym momencie niektóre binarne wartości doulbe będzie nieograniczone w systemie dziesiętnym.

Dla binarnej reprezentacji można po prostu wykorzystać mantysę i umieścić kropkę dziesiętną w odpowiednim położeniu (dopełnienie zerami, jeżeli jest to konieczne.

+0

Większość wartości dziesiętne non całkowitymi nie mogą być reprezentowane jako liczby binarne, na przykład 0,1. więc będzie on przybliżony do 0,10000000000000000000001 lub podobnego. Może powinieneś pomyśleć o tym, jak duży może być błąd przedstawionej reprezentacji (lub ile znaczących digis zostało w poprzednim obliczeniu). – rurouni

+0

Niestety, brakowało mi pytania dotyczącego liczb całkowitych, ale zostawię to na wypadek, gdyby ktoś mógł użyj go ;-) – rurouni

1

Domyślnie tryb zaokrąglania w górę do DecimalFormat. Można ustawić inny format zaokrąglania jak na swoje requiremnet wykorzystaniem setRoundingMode() metody Kod

Sample aby ustawić tryb zaokrąglania

double d = 1.2345678; 
     DecimalFormat df = new DecimalFormat("#.####"); 
     df.setRoundingMode(RoundingMode.DOWN); 
     System.out.print(df.format(d));//result 1.2345 because of rounding down 
+0

"jak mogę się upewnić, że liczba nigdy się nie zaokrągla" –

+0

@ Jean-FrançoisCorbett: nie możesz, chyba że używasz binarnego lub dowolnego systemu bazowego 2^n numer (np. ósemkowy lub szesnastkowy) – rurouni

+0

Jasne, wiem o arytmetyzacji zmiennoprzecinkowej, ale nie o to chodzi. Jak mogę się upewnić, że reprezentacja ciąg numeru nie otrzyma zaokrągloną do czegoś innego niż '„”+ d'? Ta odpowiedź * wyraźnie * zaokrągla to, co jest dokładnym przeciwieństwem tego, o co prosiłem. –

Powiązane problemy