Konvertering mellem romerske og arabiske tal i Java

1. Introduktion

De gamle romere udviklede deres eget numeriske system kaldet romertal. Systemet bruger bogstaver med forskellige værdier til at repræsentere tal. Romerske tal bruges stadig i dag i nogle mindre applikationer.

I denne vejledning implementerer vi enkle konvertere, der transformerer tal fra det ene system til det andet.

2. Romerske tal

I det romerske system har vi det 7 symboler, der repræsenterer tal:

  • jeg repræsenterer 1
  • V repræsenterer 5
  • x repræsenterer 10
  • L repræsenterer 50
  • C repræsenterer 100
  • D repræsenterer 500
  • M repræsenterer 1000

Oprindeligt repræsenterede folk en 4 med IIII eller 40 med XXXX. Dette kan være ret ubehageligt at læse. Det er også let at fejle fire symboler ved siden af ​​hinanden med tre symboler.

Romerske tal bruger subtraktiv notation for at undgå sådanne fejl. I stedet for at sige fire gange en (IIII), man kan sige, at det er en mindre end fem (IV).

Hvordan er det vigtigt i vores perspektiv? Det er vigtigt, for i stedet for blot at tilføje tal symbol for symbol, skal vi muligvis kontrollere det næste symbol for at afgøre, om nummeret skal tilføjes eller trækkes fra.

3. Model

Lad os definere et enum, der skal repræsentere de romerske tal:

enum RomanNumeral {I (1), IV (4), V (5), IX (9), X (10), XL (40), L (50), XC (90), C (100), CD ( 400), D (500), CM (900), M (1000); privat int værdi RomanNumeral (int værdi) {this.value = værdi; } public int getValue () {returværdi; } offentlig statisk liste getReverseSortedValues ​​() {return Arrays.stream (values ​​()) .sorted (Comparator.comparing ((RomanNumeral e) -> e.value) .reversed ()) .collect (Collectors.toList ()); }}

Bemærk, at vi har defineret yderligere symboler for at hjælpe med subtraktiv notation. Vi har også defineret en ekstra metode, der hedder getReverseSortedValues ​​().

Denne metode giver os mulighed for eksplicit at hente de definerede romertal i faldende værdirækkefølge.

4. Romersk til arabisk

Romerske tal kan kun repræsentere heltal mellem 1 og 4000. Vi kan bruge følgende algoritme til at konvertere et romertal til et arabisk nummer (iterere gennem symboler i omvendt rækkefølge fra M til jeg):

LET-tallet er input Streng, der repræsenterer et romersk tal LET-symbol, indstilles initialt til RomanNumeral.values ​​() [0] WHILE ciffer.længde> 0: HVIS tallet begynder med symbolets navn: tilføj symbolets værdi til resultatet, fjern symbolets navn fra talets begyndelse ELSE: indstil symbolet til det næste symbol

4.1. Implementering

Dernæst kan vi implementere algoritmen i Java:

public static int romanToArabic (String input) {String romanNumeral = input.toUpperCase (); int resultat = 0; Liste romanNumerals = RomanNumeral.getReverseSortedValues ​​(); int i = 0; mens ((romanNumeral.length ()> 0) && (i 0) {kast nyt IllegalArgumentException (input + "kan ikke konverteres til et romertal");} returnerer resultat;}

4.2. Prøve

Endelig kan vi teste implementeringen:

@Test offentligt ugyldigt givet2018Roman_WhenConvertingToArabic_ThenReturn2018 () {String roman2018 = "MMXVIII"; int resultat = RomanArabicConverter.romanToArabic (roman2018); assertThat (resultat) .isEqualTo (2018); }

5. Arabisk til romersk

Vi kan bruge følgende algoritme til at konvertere fra arabisk til romertal (iterere gennem symboler i omvendt rækkefølge fra M til jeg):

LET-nummer er et heltal mellem 1 og 4000 LET-symbol være RomanNumeral.values ​​() [0] LET resultat være en tom streng WHILE-nummer> 0: IF-symbolets værdi <= nummer: tilføj resultatet med symbolets navn, træk symbolets værdi fra tallet ELSE: vælg det næste symbol

5.1. Implementering

Dernæst kan vi nu implementere algoritmen:

offentlig statisk String arabicToRoman (int-nummer) {if ((nummer 4000)) {kast nyt IllegalArgumentException (nummer + "er ikke i området (0,4000]");} Liste romanNumerals = RomanNumeral.getReverseSortedValues ​​(); int i = 0 ; StringBuilder sb = new StringBuilder (); while ((number> 0) && (i <romanNumerals.size ())) {RomanNumeral currentSymbol = romanNumerals.get (i); if (currentSymbol.getValue () <= number) { sb.append (currentSymbol.name ()); nummer - = currentSymbol.getValue ();} ellers {i ++;}} returner sb.toString ();}

5.2. Prøve

Endelig kan vi teste implementeringen:

@Test offentligt ugyldigt given1999Arabic_WhenConvertingToRoman_ThenReturnMCMXCIX () {int arabic1999 = 1999; String result = RomanArabicConverter.arabicToRoman (arabic1999); assertThat (resultat) .isEqualTo ("MCMXCIX"); }

6. Konklusion

I denne hurtige artikel har vi vist, hvordan man konverterer mellem romerske og arabiske tal.

Vi har brugt en enum til at repræsentere sæt romerske tal, og vi har oprettet en hjælpeklasse til at udføre konverteringerne.

Den komplette implementering og alle tests kan findes på GitHub.