Roman numerals to integers

前端 未结 14 941
不思量自难忘°
不思量自难忘° 2020-12-05 20:56

I have a transfer with products that unfortunately has to get matched by product name. The biggest issue here is I might get duplicate products on account of roman numbers.

14条回答
  •  没有蜡笔的小新
    2020-12-05 21:20

    I landed here searching for a small implementation of a Roman Numerals parser but wasn't satisfied by the provided answers in terms of size and elegance. I leave my final, recursive implementation here, to help others searching a small implementation.


    Convert Roman Numerals by Recursion

    • The algorithm is able to non-adjacent numerals as well (f.e. XIIX).
    • This implementation may only work with well-formed (strings matching /[mdclxvi]*/i) roman numerals.
    • The implementation is not optimized for speed.
    // returns the value for a roman literal
    private static int romanValue(int index)
    {
        int basefactor = ((index % 2) * 4 + 1); // either 1 or 5...
        // ...multiplied with the exponentation of 10, if the literal is `x` or higher
        return index > 1 ? (int) (basefactor * System.Math.Pow(10.0, index / 2)) : basefactor;
    }
    
    public static int FromRoman(string roman)
    {
        roman = roman.ToLower();
        string literals = "mdclxvi";
        int value = 0, index = 0;
        foreach (char literal in literals)
        {
            value = romanValue(literals.Length - literals.IndexOf(literal) - 1);
            index = roman.IndexOf(literal);
            if (index > -1)
                return FromRoman(roman.Substring(index + 1)) + (index > 0 ? value - FromRoman(roman.Substring(0, index)) : value);
        }
        return 0;
    }
    

    Try it using this .Netfiddle: https://dotnetfiddle.net/veaNk3

    How does it work?

    This algorithm calculates the value of a Roman Numeral by taking the highest value from the Roman Numeral and adding/subtracting recursively the value of the remaining left/right parts of the literal.

    ii X iiv # Pick the greatest value in the literal `iixiiv` (symbolized by uppercase)
    

    Then recursively reevaluate and subtract the lefthand-side and add the righthand-side:

    (iiv) + x - (ii) # Subtract the lefthand-side, add the righthand-side
    (V - (ii)) + x - ((I) + i) # Pick the greatest values, again
    (v - ((I) + i)) + x - ((i) + i) # Pick the greatest value of the last numeral compound
    

    Finally the numerals are substituted by their integer values:

    (5 - ((1) + 1)) + 10 - ((1) + 1)
    (5 - (2)) + 10 - (2)
    3 + 10 - 2
    = 11
    

提交回复
热议问题