商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Python使用Tkinter实现一个罗马数字转整数的简单工具

Python使用Tkinter实现一个罗马数字转整数的简单工具

  发布于2026-06-29 阅读(0)

扫一扫,手机访问

之前看到 TkDocs 教程里有个用 Tkinter 做图形界面的入门例子,感觉挺实用的。正好手头有个小需求——写一个正整数和罗马数字互相转换的工具,就想着拿这个例子练练手。网上已经有文章把“整数转罗马数字”的部分讲清楚了,那咱们今天就来聊聊反向操作:怎么把罗马数字正确解析成整数。

正文

如何将罗马数字转化为正整数

转换规则其实不复杂,可以参考 LeetCode 第 13 题“罗马数字转整数”的思路。拿 MMMXCIV 举个例子,手动拆解的话,可以分成三部分:MMM 表示 3000,XC 表示 90,IV 表示 4,加起来就是 3094。但代码实现时不用这么麻烦,有更简洁的方式——从左到右遍历字符,累加对应的数值,同时注意一个细节:如果当前字符的值比前一个字符的值大,说明遇到了“减法”组合,需要把之前多加的那部分减掉两倍。具体实现如下:

def to_int(roman):
    mapping = {
        "I": 1,
        "V": 5,
        "X": 10,
        "L": 50,
        "C": 100,
        "D": 500,
        "M": 1000
    }
    result = 0
    prev_value = 0
    for char in roman:
        curr_value = mapping[char]
        result += curr_value
        if prev_value != 0 and prev_value < curr_value:
            result -= prev_value * 2
        prev_value = curr_value
    return result

检查输入是否合法

光有转换函数还不够,用户输入可能是乱写的。比如 IIMMM 按上面的逻辑会算出 3000,但它根本不是合法的罗马数字(3000 的正确写法是 MMM)。所以必须加一层输入校验。

之前那篇整数转罗马数字的文章里提到,我们可以分别处理千位、百位、十位、个位,每一位的合法组合是有限的。以个位为例,如果个位数字不是 0,那么合法的罗马数字就只有这几种:

个位上的数字对应的罗马数字
1I
2II
3III
4IV
5V
6VI
7VII
8VIII
9IX

用正则表达式暴力写当然可以,但更优雅的方式是合并同类项:1、2、3 可以合并成 I{1,3},5、6、7、8 合并成 VI{0,3},再加上 IVIX,最后补上 0 的情况(即空字符串)。这样个位的正则就是:

I{0,3}|IV|VI{0,3}|IX

同样的思路,十位、百位、千位的合法模式也能推导出来:

  • 十位:X{0,3}|XL|LX{0,3}|XC
  • 百位:C{0,3}|CD|DC{0,3}|CM
  • 千位:M{0,3}

把四部分拼起来,完整的正则表达式就是:

M{0,3}(C{0,3}|CD|DC{0,3}|CM)(X{0,3}|XL|LX{0,3}|XC)(I{0,3}|IV|VI{0,3}|IX)

注意,这个正则也会匹配空字符串,所以判断时还得额外排除掉 ""

完整的代码

参考 TkDocs 里“A First (Real) Example”的界面结构,可以直接写出下面的 Python 3 代码:

from tkinter import *
from tkinter import ttk
import re

def convert():
    try:
        raw = roman.get().strip()
        if raw == "":
            result.set("无效输入")
            return
        if re.match("^(M{0,3})(C{0,3}|CD|DC{0,3}|CM)(X{0,3}|XL|LX{0,3}|XC)(I{0,3}|IV|VI{0,3}|IX)$", raw):
            result.set(to_int(raw))
        else:
            result.set("无效输入")
            return
    except ValueError:
        pass

def to_int(roman):
    mapping = {
        "I": 1,
        "V": 5,
        "X": 10,
        "L": 50,
        "C": 100,
        "D": 500,
        "M": 1000
    }
    result = 0
    prev_value = 0
    for char in roman:
        curr_value = mapping[char]
        result += curr_value
        if prev_value != 0 and prev_value < curr_value:
            result -= prev_value * 2
        prev_value = curr_value
    return result


root = Tk()
root.title("罗马数字转整数小工具")

mainframe = ttk.Frame(root, padding=(3, 3, 12, 12))
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))

roman = StringVar()
roman_entry = ttk.Entry(mainframe, width=12, textvariable=roman)
roman_entry.grid(column=2, row=1, sticky=(W, E))

ttk.Button(mainframe, text="转化为整数", command=convert).grid(column=1, row=2, sticky=W)

ttk.Label(mainframe, text="请输入一个罗马数字").grid(column=1, row=1, sticky=W)

result = StringVar()
ttk.Label(mainframe, textvariable=result).grid(column=2, row=2, sticky=W)

root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
mainframe.columnconfigure(2, weight=1)
for child in mainframe.winfo_children(): 
    child.grid_configure(padx=5, pady=5)

roman_entry.focus()
root.bind("", convert)

root.mainloop()

运行

把上面的代码保存为 from_roman.py,然后在终端里执行:

python3 from_roman.py

运行效果如下:

Python使用Tkinter实现一个罗马数字转整数的简单工具

输入一个合法的罗马数字,比如 MCMXCVII,点击“转化为整数”按钮,就能看到结果:

Python使用Tkinter实现一个罗马数字转整数的简单工具

再用 MMMXCIV 验证一下,结果也是对的:

Python使用Tkinter实现一个罗马数字转整数的简单工具

运行结果符合预期。这个工具虽然简单,但把罗马数字解析的常见坑(非法输入、减法规则)都覆盖了,可以直接复用或扩展。

本文转载于:https://www.jb51.net/python/365329c43.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

产品推荐

热门关注