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

 更新时间:2026年06月08日 08:48:58   作者:金銀銅鐵  
本文详细介绍了使用Tkinter实现罗马数字转整数的功能,通过正则表达式验证罗马数字合法性,并百位X十位C千位M并结合Tkinter生成图形化界面,提供用户输入和转化功能,适合Python和Tkinter初学者学习,需要的朋友可以参考下

背景

TkDocs tutorial 里介绍了 Tkinter,其中有 A First (Real) Example 一文,这篇文章里有一个使用 Tkinter生成图形化界面的简单例子。我想在那篇文章的基础上实战一下,于是想到可以写一个正整数和罗马数字互相转化的简易工具。用 Tkinter 实现一个简单的罗马数字转化工具 一文中已经提供了可以将正整数转化为罗马数字的代码,本文会探讨如何进行将罗马数字转化为正整数。

正文

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

转化规则可以参考 13. 罗马数字转整数 这道题。以 MMMXCIV\text{MMMXCIV}MMMXCIV 为例,如果需要手动转化的话,可以这样分析:将 MMMXCIV\text{MMMXCIV}MMMXCIV 视为以下三部分

  • MMM:表示 3000
  • XC:表示 90
  • IV:表示 4

因此 MMMXCIV对应的整数是 3000+90+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

检查输入是否合法

上一小节提供的 to_int 方法可以将合法的罗马数字转化为对应的正整数,但也要考虑到用户的输入可能非法。例如 IIMMM按照 to_int 方法的逻辑,会被处理成 3000,但是 IIMMM 不是合法的罗马数字(3000对应的罗马数字是 MMM)。用 Tkinter 实现一个简单的罗马数字转化工具 一文提到,我们把整数转化为罗马数字时,可以分别处理千位/百位/十位/个位,这几位是独立的。以个位为例,如果个位不是 000 的话,那么合法的情况只有以下 9 种

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

那么对应的正则表达式可以写成 I|II|III|IV|V|VI|VII|VIII|IX。但是这样写太暴力了,可以将 1,2,3的情况合并,将 5,6,7,8 的情况合并。合并后变为 I{1,3}|IV|VI{0,3}|IX,再加上个位为 000 的情况,正则表达式变为 ⬇️

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)

"" 也满足这个正则表达式,但是我们需要排除掉 ""

完整的代码

A First (Real) Example 一文中有使用Tkinter生成图形化界面的简单例子。在它的基础上,可以写出以下 Python3代码

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("<Return>", convert)

root.mainloop()

运行

请将上一小节展示的完整代码保存为 from_roman.py。使用如下命令可以运行 from_roman.py

python3 from_roman.py

运行效果如下

我们输入一个合法的罗马数字,例如 MCMXCVII,然后点击“转化为罗马数字”按钮,效果如下

再用其他罗马数字验证一下(例如 MMMXCIV),效果如下

运行结果符合预期。

以上就是Python使用Tkinter实现一个罗马数字转整数的简单工具的详细内容,更多关于Python Tkinter罗马数字转整数的资料请关注脚本之家其它相关文章!

相关文章

  • Python详细对比讲解break和continue区别

    Python详细对比讲解break和continue区别

    这篇文章主要介绍了python循环控制语句 break 与 continue,break就像是终止按键,不管执行到哪一步,只要遇到break,不管什么后续步骤,直接跳出当前循环
    2022-06-06
  • Python readline()和readlines()函数实现按行读取文件

    Python readline()和readlines()函数实现按行读取文件

    本文主要介绍了Python readline()和readlines()函数实现按行读取文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • 在服务器上运行python文件详细步骤

    在服务器上运行python文件详细步骤

    很多小伙伴想知道如何在服务器上跑python程序的方法,那么这篇文章主要给大家介绍了关于在服务器上运行python文件的详细步骤,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • python实现无边框进度条的实例代码

    python实现无边框进度条的实例代码

    这篇文章主要介绍了python实现无边框进度条的实例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • Pandas.DataFrame重置Series的索引index(reset_index)

    Pandas.DataFrame重置Series的索引index(reset_index)

    本文主要介绍了Pandas.DataFrame重置Series的索引index(reset_index),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • 通过Python读取照片的Exif信息解锁图片背后的故事

    通过Python读取照片的Exif信息解锁图片背后的故事

    这篇文章主要为大家介绍了通过Python读取照片的Exif信息解锁图片背后的故事探究,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 从原理到实战拆解Python Socket通信的完整指南

    从原理到实战拆解Python Socket通信的完整指南

    网络通信是现代编程的核心能力之一,本文我们就来全方位解锁Python Socket通信的奥秘,从基础概念拆解到实战代码落地,从流程梳理到避坑指南,每一步都讲透讲细,无论是编程新手还是需要查漏补缺的开发者,都能快速掌握这一核心技
    2026-03-03
  • 使用python将csv数据导入mysql数据库

    使用python将csv数据导入mysql数据库

    这篇文章主要为大家详细介绍了如何使用python将csv数据导入mysql数据库,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-05-05
  • Python多线程threading创建及使用方法解析

    Python多线程threading创建及使用方法解析

    这篇文章主要介绍了Python多线程threading创建及使用方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 详解python如何在django中为用户模型添加自定义权限

    详解python如何在django中为用户模型添加自定义权限

    这篇文章主要介绍了python如何在django中为用户模型添加自定义权限,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10

最新评论