13-romanToInt.js 2 KB
/**
 * @param {string} s
 * @return {number}
 */

// 定义罗马数字和对应的整数值映射表
const romanToIntegerMap = new Map([
    ['I', 1],
    ['V', 5],
    ['X', 10],
    ['L', 50],
    ['C', 100],
    ['D', 500],
    ['M', 1000]
]);

/**
 * 将罗马数字转换为整数。
 * @param {string} romanNumeral - 罗马数字字符串。
 * @returns {number} 转换后的整数值。
 */
function romanToInt(romanNumeral) {
    // 使用正则表达式验证罗马数字的格式是否正确
    // M{0,4} - 最多4个M(1000)
    // (CM|CD|D?C{0,3}) - 百位数的表示:900(CM)或400(CD)或[500(D)]+[0-3个C]
    // (XC|XL|L?X{0,3}) - 十位数的表示:90(XC)或40(XL)或[50(L)]+[0-3个X]
    // (IX|IV|V?I{0,3}) - 个位数的表示:9(IX)或4(IV)或[5(V)]+[0-3个I]
    const regex = /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/;
    if (!regex.test(romanNumeral)) {
        throw new Error('Invalid Roman Numeral: ' + romanNumeral);
    }

    let total = 0;
    for (let i = 0; i < romanNumeral.length; i++) {
        const currentChar = romanNumeral[i];
        const currentValue = romanToIntegerMap.get(currentChar);

        // 验证字符的有效性
        if (!currentValue) {
            throw new Error('Wrong Roman Number');
        }

        // 处理特殊情况:如果当前数字小于下一个数字,则需要减去当前数字
        // 例如:IV = 5 - 1 = 4,IX = 10 - 1 = 9
        if (i + 1 < romanNumeral.length && romanToIntegerMap.get(romanNumeral[i + 1]) > currentValue) {
            total -= currentValue;
        } else {
            // 常规情况:直接将当前数字加到总和中
            total += currentValue;
        }

        // 调试信息:显示每一步的计算过程
        console.info(i, '-', currentChar, ':', currentValue, '=', total);
    }

    return total;
}

// 测试代码:将罗马数字 'MCMXCIV' (1994) 转换为整数
const romanInput = 'MCMXCIV';
console.info(`The integer value of ${romanInput} is ${romanToInt(romanInput)}.`);