Konvertieren zwischen römischen und arabischen Ziffern in Java

Konvertieren zwischen römischen und arabischen Ziffern in Java

1. Einführung

Die alten Römer entwickelten ein eigenes Zahlensystem, das als römische Zahlen bezeichnet wurde. Das System verwendet Buchstaben mit unterschiedlichen Werten zur Darstellung von Zahlen. In einigen kleineren Anwendungen werden noch heute römische Ziffern verwendet.

In diesem Tutorial implementieren wirsimple converters that will transform numbers from one system to the other.

2. Römische Zahlen

Im römischen System haben wir7 symbols that represent numbers:

  • I steht für 1

  • V steht für 5

  • X steht für 10

  • L steht für 50

  • C steht für 100

  • D steht für 500

  • M steht für 1000

Ursprünglich repräsentierten die Leute eine 4 mit IIII oder 40 mit XXXX. Das Lesen kann recht unangenehm sein. Es ist auch leicht, vier Symbole nebeneinander mit drei Symbolen zu verwechseln.

Roman numerals use subtractive notation, um solche Fehler zu vermeiden. Anstattfour times one (IIII) zu sagen, kann man sagen, dass esone less than five (IV) ist.

Wie wichtig ist es aus unserer Sicht? Dies ist wichtig, da wir möglicherweise nicht einfach Symbol für Symbol Zahlen hinzufügen, sondern möglicherweise das nächste Symbol überprüfen müssen, um festzustellen, ob die Zahl addiert oder subtrahiert werden soll.

3. Modell

Definieren wir eine Aufzählung zur Darstellung der römischen Ziffern:

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);

    private int value;

    RomanNumeral(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }

    public static List getReverseSortedValues() {
        return Arrays.stream(values())
          .sorted(Comparator.comparing((RomanNumeral e) -> e.value).reversed())
          .collect(Collectors.toList());
    }
}

Beachten Sie, dass wir zusätzliche Symbole definiert haben, um die subtraktive Notation zu erleichtern. Wir haben auch eine zusätzliche Methode namensgetReverseSortedValues() definiert.

Mit dieser Methode können wir die definierten römischen Ziffern in absteigender Wertereihenfolge explizit abrufen.

4. Römisch bis Arabisch

Roman numerals can only represent integers between 1 to 4000. Wir können den folgenden Algorithmus verwenden, um eine römische Zahl in eine arabische Zahl umzuwandeln (durch Symbole in umgekehrter Reihenfolge vonM nachI durchlaufen):

LET numeral be the input String representing an Roman Numeral
LET symbol be initialy set to RomanNumeral.values()[0]
WHILE numeral.length > 0:
    IF numeral starts with symbol's name:
        add symbol's value to the result
        remove the symbol's name from the numeral's beginning
    ELSE:
        set symbol to the next symbol

4.1. Implementierung

Als nächstes können wir den Algorithmus in Java implementieren:

public static int romanToArabic(String input) {
    String romanNumeral = input.toUpperCase();
    int result = 0;

    List romanNumerals = RomanNumeral.getReverseSortedValues();

    int i = 0;

    while ((romanNumeral.length() > 0) && (i < romanNumerals.size())) {
        RomanNumeral symbol = romanNumerals.get(i);
        if (romanNumeral.startsWith(symbol.name())) {
            result += symbol.getValue();
            romanNumeral = romanNumeral.substring(symbol.name().length());
        } else {
            i++;
        }
    }

    if (romanNumeral.length() > 0) {
        throw new IllegalArgumentException(input + " cannot be converted to a Roman Numeral");
    }

    return result;
}

4.2. Test

Schließlich können wir die Implementierung testen:

@Test
public void given2018Roman_WhenConvertingToArabic_ThenReturn2018() {
    String roman2018 = "MMXVIII";

    int result = RomanArabicConverter.romanToArabic(roman2018);

    assertThat(result).isEqualTo(2018);
}

5. Arabisch bis Römisch

Wir können den folgenden Algorithmus verwenden, um von arabischen in römische Ziffern umzuwandeln (durch Symbole in umgekehrter Reihenfolge vonM nachI durchlaufen):

LET number be an integer between 1 and 4000
LET symbol be RomanNumeral.values()[0]
LET result be an empty String
WHILE number > 0:
    IF symbol's value <= number:
        append the result with the symbol's name
        subtract symbol's value from number
    ELSE:
        pick the next symbol

5.1. Implementierung

Als nächstes können wir nun den Algorithmus implementieren:

public static String arabicToRoman(int number) {
    if ((number <= 0) || (number > 4000)) {
        throw new IllegalArgumentException(number + " is not in range (0,4000]");
    }

    List 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());
            number -= currentSymbol.getValue();
        } else {
            i++;
        }
    }

    return sb.toString();
}

5.2. Test

Schließlich können wir die Implementierung testen:

@Test
public void given1999Arabic_WhenConvertingToRoman_ThenReturnMCMXCIX() {
    int arabic1999 = 1999;

    String result = RomanArabicConverter.arabicToRoman(arabic1999);

    assertThat(result).isEqualTo("MCMXCIX");
}

6. Fazit

In diesem kurzen Artikel haben wir gezeigt, wie man zwischen römischen und arabischen Ziffern konvertiert.

Wir haben einenum verwendet, um die Menge der römischen Ziffern darzustellen, und wir haben eine Dienstprogrammklasse erstellt, um die Konvertierungen durchzuführen.

Die vollständige Implementierung und alle Tests finden Sie inover on GitHub.