Skip to content

M28700: 罗马数字与整数的转换

implementation, dict, greedy, http://cs101.openjudge.cn/pctbook/M28700/

罗马数字包含以下七种字符:I、V、X、L、C、D和M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 整数2写做II,即为两个并列的I。12写做XII,即为X+II。 27写做XXVII, 即为 XX+V+II。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如4不写做IIII,而是IV。I在V的左边,所表示的数等于大数5减小数1得到的数值4。同样地,数字9表示为IX。这个特殊的规则只适用于以下六种情况: I 可以放在 V (5) 和 X (10) 的左边,来表示4和9。 X 可以放在 L (50) 和 C (100) 的左边,来表示40和90。 C 可以放在 D (500) 和 M (1000) 的左边,来表示400和900。

题目要求:实现罗马数字和整数的转换。 1)如果输入是一个罗马数字,将其转换成整数; 2)如果输入是一个整数,将其转换为罗马数字。 无论是何种输入,整数在1到3999的范围内。

输入输出示例:

输入:III

输出:3

输入:4

输出:IV

输入:IX

输出:9

输入:58

输出:LVIII

输入:MCMXCIV

输出:1994

(M = 1000, CM = 900, XC = 90, IV = 4)

输入

一行字符(可能是罗马数字,也可能是正整数)

输出

如果输入是罗马数字,输出是正整数; 如果输入是正整数,输出是罗马数字。

样例输入

MCMXCIV

样例输出

1994

提示

tags: implementation 整数是正整数,数值范围1~3999。罗马数字中的字符是大写的。 可采用第一个字符判断输入是整数(0 ~ 9)还是罗马数字(不是0 ~ 9)。

思路:整数->罗⻢数字的过程中,利用字典的顺序保证优先转换大的单位

python
#段睿瞳 信管系
value_to_roman = {
    1000: 'M', 900: 'CM', 500: 'D', 400: 'CD',
    100: 'C', 90: 'XC', 50: 'L', 40: 'XL',
    10: 'X', 9: 'IX', 5: 'V', 4: 'IV', 1: 'I'
}

# 构建反向映射:罗马字符 -> 数值
roman_to_value = {v: k for k, v in value_to_roman.items()}

s = input().strip()
ans_s = ''
ans_n = 0

if s[0] in roman_to_value:
    i = 0
    while i < len(s):
        # 检查两位组合(如 IX, XL, CM 等)
        if i + 1 < len(s) and s[i:i + 2] in roman_to_value:
            ans_n += roman_to_value[s[i:i + 2]]
            i += 2
        else:
            ans_n += roman_to_value[s[i]]
            i += 1
    print(ans_n)

else:
    num = int(s)

    for value, roman in value_to_roman.items():
        count = num // value
        ans_s += roman * count
        num -= value * count
    print(ans_s)

可以写一个程序,先判断输入是数字串还是罗马数字串,然后分别处理:

  1. 罗马 → 整数
    • 按照罗马数字的规则逐个字符扫描,如果当前字符比后一个字符小,则减去它,否则加上它。
  2. 整数 → 罗马
    • 用一个从大到小的映射表(如 1000→M, 900→CM, 500→D ... ),依次减去数字,拼接对应的符号。

下面给出完整 Python 实现:

python
def roman_to_int(s: str) -> int:
    roman_map = {
        'I': 1, 'V': 5, 'X': 10, 'L': 50,
        'C': 100, 'D': 500, 'M': 1000
    }
    total = 0
    i = 0
    while i < len(s):
        # 判断是否是特殊情况
        if i + 1 < len(s) and roman_map[s[i]] < roman_map[s[i + 1]]:
            total += roman_map[s[i + 1]] - roman_map[s[i]]
            i += 2
        else:
            total += roman_map[s[i]]
            i += 1
    return total


def int_to_roman(num: int) -> str:
    val = [
        1000, 900, 500, 400,
        100, 90, 50, 40,
        10, 9, 5, 4,
        1
    ]
    syms = [
        "M", "CM", "D", "CD",
        "C", "XC", "L", "XL",
        "X", "IX", "V", "IV",
        "I"
    ]
    res = []
    for i in range(len(val)):
        while num >= val[i]:
            num -= val[i]
            res.append(syms[i])
    return "".join(res)


def main():
    s = input().strip()
    if s[0].isdigit():   # 整数输入
        num = int(s)
        print(int_to_roman(num))
    else:                # 罗马数字输入
        print(roman_to_int(s))


if __name__ == "__main__":
    main()

【刘存浩 25 地空】思考罗马数字怎么合理的转换为阿拉伯数字,最后想到可以倒序计数从而解决了那几种特殊情况

python
# 罗马数字与整数互转程序
a = input().strip()

# 映射表:整数转罗马数字(按值降序排列,包含所有特例)
int_to_roman_map = [
    (1000, 'M'),
    (900, 'CM'),
    (500, 'D'),
    (400, 'CD'),
    (100, 'C'),
    (90, 'XC'),
    (50, 'L'),
    (40, 'XL'),
    (10, 'X'),
    (9, 'IX'),
    (5, 'V'),
    (4, 'IV'),
    (1, 'I')
]

# 字符映射:罗马字符到数值
roman_to_int_map = {
    'I': 1,
    'V': 5,
    'X': 10,
    'L': 50,
    'C': 100,
    'D': 500,
    'M': 1000
}

# 判断输入类型
if a[0].isdigit():
    # 输入是整数,转换为罗马数字
    num = int(a)
    result = ''
    for value, symbol in int_to_roman_map:
        count = num // value
        if count > 0:
            result += symbol * count
            num -= value * count
    print(result)
else:
    # 输入是罗马数字,转换为整数
    # 倒序遍历,记录前一个数值,用于判断加减
    total = 0
    prev_value = 0
    # 从右往左处理
    for char in reversed(a):
        current_value = roman_to_int_map[char]
        if current_value >= prev_value:
            total += current_value
        else:
            total -= current_value
        prev_value = current_value
    print(total)