En praktisk guide til DecimalFormat

1. Oversigt

I denne artikel skal vi udforske Decimalformat klasse sammen med dens praktiske anvendelser.

Dette er en underklasse af NumberFormat, som tillader formatering af decimaltal ' Snor repræsentation ved hjælp af foruddefinerede mønstre.

Det kan også bruges omvendt til at analysere strenge i tal.

2. Hvordan fungerer det?

For at formatere et nummer skal vi definere et mønster, som er en række af specialtegn, der potentielt er blandet med tekst.

Der er 11 specielle mønstertegn, men de vigtigste er:

  • 0 - udskriver et ciffer, hvis det er angivet, 0 ellers
  • # - udskriver et ciffer, hvis det er angivet, intet andet
  • . - angiv, hvor decimalseparatoren skal placeres
  • , - angiv hvor grupperingsseparatoren skal placeres

Når mønsteret anvendes på et tal, udføres dets formateringsregler, og resultatet udskrives i henhold til DecimalFormatSymbol af vores JVM'er Lokal medmindre en specifik Lokal er specificeret.

Følgende eksemplers output er fra en JVM, der kører på en engelsk Lokal.

3. Grundlæggende formatering

Lad os nu se, hvilke output der produceres, når vi formaterer det samme nummer med følgende mønstre.

3.1. Enkle decimaler

dobbelt d = 1234567.89; assertThat (ny DecimalFormat ("#. ##"). format (d)). er EqualTo ("1234567.89"); assertThat (nyt DecimalFormat ("0.00"). format (d)). er EqualTo ("1234567.89"); 

Som vi kan se, kasseres heltalets del aldrig, uanset om mønsteret er mindre end antallet.

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

Hvis mønsteret i stedet er større end antallet, tilføjes nuller, mens hashes falder, både i heltal og i decimaldele.

3.2. Afrunding

Hvis decimaldelen af ​​mønsteret ikke kan indeholde hele nøjagtigheden af ​​inputnummeret, bliver det afrundet.

Her er .89-delen afrundet til .90, så er 0 blevet droppet:

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

Her er .89-delen afrundet til 1,00, derefter er 0,00 faldet, og 1 er opsummeret til 7:

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

Standard afrundingstilstand er HALF_EVEN, men det kan tilpasses gennem setRoundingMode metode.

3.3. Gruppering

Grupperingsseparatoren bruges til at specificere et undermønster, som gentages automatisk:

assertThat (ny DecimalFormat ("#, ###. #"). format (d)) .isEqualTo ("1.234.567.9"); assertThat (ny DecimalFormat ("#, ###"). format (d)) .isEqualTo ("1.234.568"); 

3.4. Flere grupperingsmønstre

Nogle lande har et variabelt antal grupperingsmønstre i deres nummereringssystemer.

Det indiske nummereringssystem bruger formatet #, ##, ###. ##, hvor kun den første grupperingsseparator har tre tal, mens alle de andre har to tal.

Dette er ikke muligt at opnå ved hjælp af Decimalformat klasse, der kun beholder det seneste mønster, der er stødt på fra venstre mod højre, og anvender det på hele nummeret, idet man ignorerer tidligere grupperingsmønstre.

Et forsøg på at bruge mønsteret #, ##, ##, ##, ### vil resultere i en omgruppering til #######, ### og ender i en omfordeling til #, ###, # ##, ###.

For at opnå matchning med flere grupperingsmønstre er det nødvendigt at skrive vores eget Snor manipulationskode, eller alternativt for at prøve Icu4J'erne Decimalformat, som tillader det.

3.5. Mixing String Literals

Det er muligt at blande Snor bogstaver i mønsteret:

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

Det er også muligt at bruge specialtegn som Snor bogstaver, gennem undslippe:

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

4. Lokaliseret formatering

Mange lande bruger ikke engelske symboler og bruger kommaet som decimalseparator og prikken som grupperingsseparator.

Kører mønsteret #, ###. ## på en JVM med en italiensk Lokalfor eksempel output 1.234.567,89.

Selvom dette i nogle tilfælde kan være en nyttig i18n-funktion, vil vi måske i andre måske håndhæve et specifikt JVM-uafhængigt format.

Sådan kan vi gø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 interesserede i, er ikke blandt dem, der er omfattet af DecimalFormatSymboler konstruktør, kan vi specificere det med getInstance metode:

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

5. Videnskabelige notationer

Den videnskabelige notation repræsenterer produktet af en Mantissa og en eksponent på ti. Tallet 1234567.89 kan også repræsenteres som 12.3456789 * 10 ^ 5 (prikken forskydes med 5 positioner).

5.1. E-Bemærkning

Det er muligt at udtrykke et tal i videnskabelig notation ved hjælp af E mønsterkarakter, der repræsenterer eksponenten af ​​ti:

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

Vi skal huske på, at antallet af tegn efter eksponenten er relevant, så hvis vi har brug for at udtrykke 10 ^ 12, har vi brug for E00 og ikke E0.

5.2. Teknisk notation

Det er almindeligt at bruge en bestemt form for videnskabelig notation kaldet Engineering Notation, som justerer resultaterne for at blive udtrykt som multiple af tre, for eksempel når man bruger måleenheder som Kilo (10 ^ 3), Mega (10 ^ 6), Giga ( 10 ^ 9) osv.

Vi kan håndhæve denne type notation ved at justere det maksimale antal heltal cifre (tegnene udtrykt med # og til venstre for decimalseparatoren), så det er højere end minimumstallet (det udtrykt med 0) og højere end 1.

Dette tvinger eksponenten til at være et multiplum af det maksimale antal, så for denne brugssag ønsker vi, at det maksimale antal 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

Lad os se, hvordan det er muligt at analysere a Snor ind 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);

Da den returnerede værdi ikke udledes af tilstedeværelsen af ​​en decimalseparator, kan vi bruge metoderne som .doubleValue (), .longValue () af de returnerede Nummer modsætter sig at håndhæve en bestemt primitiv i output.

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

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

7. Trådsikkerhed

Decimalformat er ikke trådsikker, derfor skal vi være særlig opmærksomme, når vi deler den samme forekomst mellem tråde.

8. Konklusion

Vi har set de største anvendelser af Decimalformat klasse sammen med dets styrker og svagheder.

Som altid er den fulde kildekode tilgængelig på Github.