2014-09-23 9 views
5

Jeśli sformatować podwójne przy użyciu metody toString, to otrzymam pełną precyzję podwójnego. Na przykład (stosując Scala składni)Jak mogę wyprowadzać zlokalizowane wartości zmiennoprzecinkowe Java w pełnej precyzji?

java.text.MessageFormat.format ("{0}", Math.PI.toString) 

spowoduje łańcuch zawierający:

3.141592653589793 

jednak, wartość ta jest zlokalizowany. Gdybym przechodzą podwójną wartość jako pudełkowej Double, że jest tak:

java.text.MessageFormat.format ("{0}", Math.PI.asInstanceOf[AnyRef]) 

(AnyRef jest Scala typ, który jest odpowiednikiem Object w Java), a następnie wynik jest zlokalizowana ciąg z obcinane precyzja:

3.142 

wynik jest taki sam, nawet jeśli dodać więcej podpowiedź do łańcucha format:

java.text.MessageFormat.format ("{0,number}", Math.PI.asInstanceOf[AnyRef]) 

mogę uzyskać pełną precyzję określając format niestandardowy:

java.text.MessageFormat.format ("{0,number,#.###############}", Math.PI.asInstanceOf[AnyRef]) 

ale to wymaga pewnej wiedzy o podwójnej wielkości i precyzji. Jeśli drukuję jakąkolwiek podwójną wartość (nie tylko Pi) i chcę zachować pełną precyzję wartości, to podejście to oznacza, że ​​muszę dynamicznie zmieniać ciąg formatu - i to nie jest dogodnie wygodne, jeśli (jak w w moim przypadku) łańcuch formatu jest faktycznie uzyskiwany z pakunku zasobów. Na przykład rozważ podwójną wartość . Konwertowanie na ciąg znaków jako pierwsze i użycie "{0}" jako ciągu formatu powoduje, że odpowiednia, ale nieokreślona, ​​wartość ciągu znaków to 1.0E37. Jeśli przekażę to jako zapakowany Double z ciągiem formatu "{0, numer}", otrzymam śmieszną wartość 10,000,000,000,000,000,000,000,000,000,000,000,000.

Podsumowując, nie mogę znaleźć ciągu formatu, który zachowuje pełną precyzję podwójnego kształtu bez uprzedniego przekonwertowania go na ciąg znaków - i to jest coś, co wolałbym uniknąć, tak jak zarazy. Czy istnieje ciąg formatu liczbowego, który wyświetla pełną dokładność podwójnego jako zlokalizowanej wartości?

UPDATE:

Właśnie w celu wyjaśnienia, dlaczego wolałbym nie mieć do konwersji podwójnych do strun:

  • toString powrotów, o ile jestem w stanie powiedzieć, ważny Java podwójna wartość dosł. Jako ciąg wynik nie jest zlokalizowany po przekazaniu do MessageFormat.format. Na przykład powiedzmy, że chcę wyprowadzić zlokalizowaną postać o wartości 1234.567. toString zwróci "1234.567", a MessageFormat.format zostawi to na tym. W porządku. Mam swoją dokładność. Jednak w Niemczech miałoby to więcej sensu, gdyby pojawił się jako "1.234,567". Nawet w USA/Wielkiej Brytanii wyglądałoby to ładniej, gdyby wyglądało na "1,234.567".
  • Jeśli mijam zapakowane Integer, Boolean, lub inny niż zmiennoprzecinkowych prymitywny typ do MessageFormat.format (z prostym „{n}” format), a potem się ładnie zlokalizowana, pełna moc precyzja. Nie potrzebuję - i nie powinienem, ponieważ stracę zlokalizowane dane wyjściowe - najpierw konwertuj te wartości na ciągi. Oznacza to, że muszę traktować double (i float oraz BigDecimal s) inaczej i konwertować je na ciągi przed przekazaniem ich do MessageFormat.format. (Co więcej, muszę to robić za każdym razem.)
+1

"BigDecimal" może? –

+0

Nie potrzebuję "BigDecimal" - regularne podwójne jest w porządku dla moich celów. Konwersja do BigDecimal jest tak samo uciążliwa dla mnie jak konwersja na ciąg znaków. –

+0

Po prostu próbowałem konwertować 'PI' na BigDecimal i wyprowadzałem ... ... i otrzymałem' 3.142', więc to też nie działa. ;-) –

Odpowiedz

-1

Format podwójny w Javie reprezentowany jest przez 64 bity, a do mantysy używane są 52 bity. log (2) = 15.65355977. Oznacza to, że precyzja Double jest z grubsza 15-16 cyfr.

Więc myślę, że wynik 3.141592653589793 jest prawie wszystkim, co można uzyskać z Double.

+0

Pytanie brzmiało: _ Czy istnieje ciąg formatu liczbowego, który wyprowadza pełną precyzję podwójnego? _ Nie jest to kwestia zwiększania precyzji wartości zmiennoprzecinkowej, ale pytanie o wyprowadzanie wartości przechowywanej w podwójnym z jak największą dokładnością. Zwróciłem uwagę, że uzyskujesz pełną precyzję, jeśli najpierw przekształcisz podwójną wartość w ciąg znaków, ale nie wydaje się, aby można to było zrobić za pomocą 'MessageFormat'. –

+0

@MikeAllen przykro mi, przegapiłem punkt twojego pytania. Wróć do tematu. Wygląda na to, że nie ma prostego i jasnego sposobu na to, aby format MessageFormat był podwajany, jak chcesz. Mogę tylko wskazać, że nadanie niestandardowego wzorca jak "#. ##########################" będzie działało (jak wspomniałeś), ale nie robi faktycznie wymagają wiedzy na temat precyzji Double'a. Możesz podać dowolną liczbę cyfr po punkcie, a to zadziała. Być może możesz rozważyć utworzenie stałego formatu z kilkoma dodatkowymi cyframi w ogonie i używanie go w razie potrzeby. – Aivean

+0

Dzięki za odpowiedź. Problem, z którym próbuję się komunikować, polega na tym, że niestandardowe formaty, w taki czy inny sposób, obcinają dokładność/precyzję wyjściowej wartości. Gdybym wiedział, że wielkość podwójnej wartości mieści się, powiedzmy, w przedziale 1-10, to format, który określisz będzie w porządku. Ale co, jeśli wartość wynosiła 1,2345E-37? Twój format wypisze 0,000000000000000 - więc stracę * wszystko * precyzję! –

0

MessageFormat używa zlokalizowanej reprezentacji, z separatorami tysięcy, może przecinkiem dziesiętnym i tak dalej. W twoim użyciu używa domyślnego ustawienia narodowego twojej platformy.

Coś należy trzymać oddzielnie od notacji uniwersalnego programisty, valueOf/toString.

Używanie double i precision jest trochę oksymoronu, ponieważ dziesiętna reprezentacja jest przybliżeniem sumy potęg 2, że podwójne jest wewnętrznie.

Aby zachować pełną informację, można przechowywać surowe bity w formie tekstowej, używając numeru Double.doubleToRawLongBits i w drodze powrotnej longBitsToDouble.

double x = Math.PI; 
String repr = String.format("%016x", Double.doubleToRawLongBits(x)); 
x = Double.longBitsToDouble(Long.valueOf(repr, 16)); 
+0

Dzięki za komentarze. Rozumiem, że podwojenia są przechowywane wewnętrznie i rozumiem, że nie ma w 100% dokładnego sposobu reprezentowania tej wartości jako ciągu dziesiętnego. Mam jednak nadzieję, że zgodzisz się, że 'toString' wykonuje całkiem niezłą robotę, wypisując pełną zawartość podwójnej wartości w formie czytelnej dla człowieka. Po prostu chcę tej samej wierności przy użyciu 'MessageFormat.format' z podwójnym. Twoja sugestia zachowuje dokładność, ale większość ludzi będzie walczyć o zrozumienie przedstawionej wartości. –

+0

Tak się bałem. Było kiedyś pytanie SO na temat maksymalnej liczby miejsc w podwójnym, jak ten [jak-wiele-dziesiętnych-miejsc-w-podwójne-java]. (Http://stackoverflow.com/questions/3334168/ ile-dziesiętnie-miejsca-w-podwójnej-java). –

Powiązane problemy