1前書き

古代ローマ人はローマ数字と呼ばれる独自の数字システムを開発しました。システムは、数値を表すためにさまざまな値の文字を使用します。ローマ数字はまだいくつかのマイナーなアプリケーションで今日使用されています。

このチュートリアルでは、あるシステムから別のシステムに数値を変換する** 簡単なコンバータを実装します。


2ローマ数字

ローマ字では、数字を表す** 7記号があります。


  • I

    は1を表します


  • V

    は5を表します


  • X

    は10を表します


  • L

    は50を表します


  • C

    は100を表します


  • D

    は500を表します


  • M

    は1000を表します

もともと、人々は以前はIIIIで4またはXXXXで40を表していました。これを読むのはかなり不快です。 3つのシンボルを4つのシンボルを隣り合わせに間違えるのも簡単です。

  • ローマ数字はそのような間違いを避けるために減法** を使います。

4回1回ではなく(IIII)、5回未満であると言えます(IV)。

私たちの観点からそれはどのように重要ですか?シンボルごとに数字を単純に加算するのではなく、次のシンボルをチェックして、数字を加算または減算する必要があるかどうかを判断する必要がある場合があるため、重要です。


3モデル

ローマ数字を表す列挙型を定義しましょう。

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<RomanNumeral> getReverseSortedValues() {
        return Arrays.stream(values())
          .sorted(Comparator.comparing((RomanNumeral e) -> e.value).reversed())
          .collect(Collectors.toList());
    }
}

減法表記に役立つように追加のシンボルを定義したことに注意してください。

getReverseSortedValues()

という名前の追加メソッドも定義しました。

このメソッドにより、定義されたローマ数字を降順に明示的に取得することができます。


4ローマからアラビア語

  • ローマ数字は1から4000までの整数を表すことができます** 。以下のアルゴリズムを使用して、ローマ数字をアラビア数字に変換することができます(

    M

    から

    I

    への逆の順序でシンボルを反復します)。

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. 実装

次に、このアルゴリズムをJavaで実装できます。

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

    List<RomanNumeral> 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
public void given2018Roman__WhenConvertingToArabic__ThenReturn2018() {
    String roman2018 = "MMXVIII";

    int result = RomanArabicConverter.romanToArabic(roman2018);

    assertThat(result).isEqualTo(2018);
}

** 5アラビア語からローマ字へ

次のアルゴリズムを使用して、アラビア語からローマ数字に変換することができます(

M

から

I

に逆の順序で記号を繰り返し処理します)。

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. 実装

次に、アルゴリズムを実装しましょう。

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

    List<RomanNumeral> 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
public void given1999Arabic__WhenConvertingToRoman__ThenReturnMCMXCIX() {
    int arabic1999 = 1999;

    String result = RomanArabicConverter.arabicToRoman(arabic1999);

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


6. 結論

この簡単な記事では、ローマ数字とアラビア数字を変換する方法を説明しました。

ローマ数字のセットを表すために

enum

を使用し、変換を実行するためのユーティリティクラスを作成しました。

完全な実装とすべてのテストはhttps://github.com/eugenp/tutorials/tree/master/algorithms-miscellaneous-2[over on GitHub]にあります。