D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 3230 - std.conv should provide facilities for converting from Roman numerals.
Summary: std.conv should provide facilities for converting from Roman numerals.
Status: RESOLVED WONTFIX
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P2 enhancement
Assignee: Andrei Alexandrescu
URL:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2009-08-05 08:22 UTC by David Simcha
Modified: 2015-06-09 01:28 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description David Simcha 2009-08-05 08:22:53 UTC
Pretty simple, without further ado here's the patch.  Just to be absolutely clear, I wrote this code snippet entirely by myself and hereby release it into the public domain.

// Converts a single digit from Roman to arabic.
private uint convertDigit(char digit) pure {
    switch(digit) {
        case 'I' :
            return 1;
        case 'V' :
            return 5;
        case 'X' :
            return 10;
        case 'L' :
            return 50;
        case 'C' :
            return 100;
        case 'D' :
            return 500;
        case 'M' :
            return 1000;
        default :
            throw new ConvError(
                "Could not convert Roman digit " ~ digit ~ " to a number.");
    }
    assert(0);
}

/**Converts a string containing a Roman numeral to an unsigned integer
 * representation.
 *
 * Throws:  ConvError on invalid Roman digit.
 */
uint romanToInt(const char[] roman) pure {
    uint result = 0;
    uint maxDigit = 0;

    for(size_t i = roman.length - 1; i != size_t.max; i--) {
        auto romanDigit = roman[i];
        uint arabic = convertDigit(romanDigit);

        if(arabic > maxDigit) {
            maxDigit = arabic;
        }

        // Should we add or subtract?
        if(arabic >= maxDigit) {
            result += arabic;
        } else {
            result -= arabic;
        }
    }
    return result;
}

unittest {
    assert(romanToInt("XIX") == 19);
    assert(romanToInt("DCLXVI") == 666);
    assert(romanToInt("XXX") == 30);
    assert(romanToInt("MDCCCLXXXVIII") == 1888);
    assert(romanToInt("XCIX") == 99);
    assert(romanToInt("XLIX") == 49);
    assert(romanToInt("IV") == 4);
    assert(romanToInt("XLV") == 45);
}
Comment 1 Don 2009-09-08 09:46:17 UTC
Is this sufficiently commonly used that it belongs in the standard library? My feeling is that the standard library would need to get very large before this sort of stuff is in there. Do other languages include it?
Comment 2 Andrei Alexandrescu 2010-10-02 19:05:30 UTC
This is a bit too exotic for inclusion in the standard library. If people feel differently, please reopen and discuss.