En praktisk guide til desimalformat

1. Oversikt

I denne artikkelen skal vi utforske Desimalformat klasse sammen med dens praktiske bruksområder.

Dette er en underklasse av NumberFormat, som tillater formatering av desimaltall ' String representasjon ved hjelp av forhåndsdefinerte mønstre.

Den kan også brukes omvendt for å analysere strenger i tall.

2. Hvordan fungerer det?

For å formatere et tall, må vi definere et mønster, som er en sekvens av spesialtegn som potensielt kan blandes med tekst.

Det er 11 spesielle mønstertegn, men de viktigste er:

  • 0 - skriver ut et siffer hvis gitt, 0 ellers
  • # - skriver ut et siffer hvis det er angitt, ingenting annet
  • . - angi hvor du skal sette desimalseparatoren
  • , - angi hvor grupperingsskilleren skal plasseres

Når mønsteret blir brukt på et tall, blir formateringsreglene utført, og resultatet skrives ut i henhold til DesimalFormatSymbol av våre JVM-er Lokal med mindre en spesifikk Lokal er spesifisert.

Følgende eksemplers utganger er fra en JVM som kjører på en engelsk Lokal.

3. Grunnleggende formatering

La oss nå se hvilke utganger som produseres når vi formaterer samme nummer med følgende mønstre.

3.1. Enkle desimaler

dobbelt d = 1234567.89; assertThat (new DecimalFormat ("#. ##"). format (d)). isEqualTo ("1234567.89"); assertThat (new DecimalFormat ("0.00"). format (d)). isEqualTo ("1234567.89"); 

Som vi kan se, blir hele delen aldri kastet, uansett om mønsteret er mindre enn tallet.

assertThat (new DecimalFormat ("#########. ###"). format (d)) .isEqualTo ("1234567.89"); assertThat (new DecimalFormat ("000000000.000"). format (d)) .isEqualTo ("001234567.890"); 

Hvis mønsteret i stedet er større enn tallet, blir nuller lagt til, mens hashes faller, både i heltallet og i desimaldelene.

3.2. Avrunding

Hvis desimaldelen av mønsteret ikke kan inneholde hele presisjonen til inngangsnummeret, blir det avrundet.

Her har .89-delen blitt avrundet til .90, så er 0 falt:

assertThat (new DecimalFormat ("#. #"). format (d)) .isEqualTo ("1234567.9"); 

Her har .89-delen blitt avrundet til 1,00, deretter har 00 blitt droppet og 1 har blitt oppsummert til 7:

assertThat (new DecimalFormat ("#"). format (d)) .isEqualTo ("1234568"); 

Standard avrundingsmodus er HALF_EVEN, men det kan tilpasses gjennom setRoundingMode metode.

3.3. Gruppering

Grupperingsskilleren brukes til å spesifisere et undermønster som blir gjentatt automatisk:

assertThat (new DecimalFormat ("#, ###. #"). format (d)) .isEqualTo ("1,234,567.9"); assertThat (new DecimalFormat ("#, ###"). format (d)) .isEqualTo ("1,234,568"); 

3.4. Flere grupperingsmønstre

Noen land har et variabelt antall grupperingsmønstre i nummereringssystemene sine.

Det indiske nummereringssystemet bruker formatet #, ##, ###. ##, der bare den første grupperingsskilleren har tre tall, mens alle de andre har to tall.

Dette er ikke mulig å oppnå ved hjelp av Desimalformat klasse, som bare holder det siste mønsteret fra venstre til høyre, og bruker det på hele tallet, og ignorerer tidligere grupperingsmønstre.

Et forsøk på å bruke mønsteret #, ##, ##, ##, ### vil resultere i en omgruppering til #######, ### og ende i en omfordeling til #, ###, # ##, ###.

For å oppnå samsvar med flere grupperingsmønstre er det nødvendig å skrive vårt eget String manipulasjonskode, eller alternativt for å prøve Icu4J-ene Desimalformat, som tillater det.

3.5. Mixing String Literals

Det er mulig å blande String bokstaver i mønsteret:

assertThat (new DecimalFormat ("The # number") .format (d)) .isEqualTo ("The 1234568 number"); 

Det er også mulig å bruke spesialtegn som String bokstaver, gjennom å rømme:

assertThat (new DecimalFormat ("The # # # number") .format (d)) .isEqualTo ("The # 1234568 number"); 

4. Lokalisert formatering

Mange land bruker ikke engelske symboler og bruker kommaet som desimalskiller og prikken som grupperingsskiller.

Kjører mønsteret #, ###. ## på en JVM med en italiensk Lokal, for eksempel, ville levere 1.234.567,89.

Selv om dette i noen tilfeller kan være en nyttig i18n-funksjon, vil vi i andre kanskje håndheve et bestemt JVM-uavhengig format.

Slik kan vi gjøre det:

assertThat (new DecimalFormat ("#, ###. ##", new DecimalFormatSymbols (Locale.ENGLISH)). format (d)) .isEqualTo ("1,234,567.89"); assertThat (new DecimalFormat ("#, ###. ##", new DecimalFormatSymbols (Locale.ITALIAN)). format (d)) .isEqualTo ("1.234.567,89"); 

Hvis den Lokal vi er interessert i er ikke blant de som dekkes av DesimalFormatSymboler konstruktør, kan vi spesifisere det med getInstance metode:

Lokal customLocale = ny lokal ("it", "IT"); assertThat (ny DecimalFormat ("#, ###. ##", DecimalFormatSymbols.getInstance (customLocale)). format (d)) .isEqualTo ("1.234.567,89");

5. Vitenskapelige notasjoner

Den vitenskapelige notasjonen representerer produktet av en Mantissa og en eksponent på ti. Tallet 1234567.89 kan også vises som 12.3456789 * 10 ^ 5 (prikken forskyves med 5 posisjoner).

5.1. E-Notasjon

Det er mulig å uttrykke et tall i Scientific Notation ved hjelp av E mønsterkarakter som representerer eksponenten av ti:

assertThat (new DecimalFormat ("00. ####### E0"). format (d)) .isEqualTo ("12.3456789E5"); assertThat (ny DecimalFormat ("000.000000E0"). format (d)) .isEqualTo ("123.456789E4"); 

Vi bør huske at antall tegn etter eksponenten er relevant, så hvis vi trenger å uttrykke 10 ^ 12, trenger vi E00 og ikke E0.

5.2. Ingeniørnotasjon

Det er vanlig å bruke en bestemt form for vitenskapelig notasjon kalt Engineering Notation, som justerer resultatene for å bli uttrykt som multiplum av tre, for eksempel når du bruker måleenheter som Kilo (10 ^ 3), Mega (10 ^ 6), Giga ( 10 ^ 9), og så videre.

Vi kan håndheve denne typen notasjon ved å justere maksimalt antall heltall (tegnene uttrykt med # og til venstre for desimalseparatoren) slik at det er høyere enn minimumstallet (det som er uttrykt med 0) og høyere enn 1.

Dette tvinger eksponenten til å være et multiplum av maksimalt antall, så for dette brukstilfellet vil vi at maksimalt antall skal være tre:

assertThat (new DecimalFormat ("## 0. ###### E0") .format (d)). isEqualTo ("1.23456789E6"); assertThat (new DecimalFormat ("###. 000000E0") .format (d)). isEqualTo ("1.23456789E6"); 

6. Analyse

La oss se hvordan det er mulig å analysere a String inn i en Nummer med analysemetoden:

assertThat (new DecimalFormat ("", new DecimalFormatSymbols (Locale.ENGLISH)) .parse ("1234567.89")) .isEqualTo (1234567.89); assertThat (new DecimalFormat ("", new DecimalFormatSymbols (Locale.ITALIAN)) .parse ("1.234.567,89")) .isEqualTo (1234567.89);

Siden den returnerte verdien ikke er utledet av tilstedeværelsen av en desimalseparator, kan vi bruke metodene som .doubleValue (), .longValue () av de returnerte Nummer objekt for å håndheve en spesifikk primitiv produksjon.

Vi kan også få en BigDecimal som følger:

NumberFormat nf = new DecimalFormat ("", new DecimalFormatSymbols (Locale.ENGLISH)); ((DecimalFormat) nf) .setParseBigDecimal (true); assertThat (nf.parse ("1234567.89")) .isEqualTo (BigDecimal.valueOf (1234567.89)); 

7. Trådsikkerhet

Desimalformat er ikke trådsikker, derfor bør vi være spesielt oppmerksomme når vi deler samme forekomst mellom tråder.

8. Konklusjon

Vi har sett de viktigste bruken av Desimalformat klasse, sammen med dets styrker og svakheter.

Som alltid er hele kildekoden tilgjengelig på Github.


$config[zx-auto] not found$config[zx-overlay] not found