Python使用Tkinter實(shí)現(xiàn)一個(gè)羅馬數(shù)字轉(zhuǎn)整數(shù)的簡(jiǎn)單工具
背景
TkDocs tutorial 里介紹了 Tkinter,其中有 A First (Real) Example 一文,這篇文章里有一個(gè)使用 Tkinter生成圖形化界面的簡(jiǎn)單例子。我想在那篇文章的基礎(chǔ)上實(shí)戰(zhàn)一下,于是想到可以寫一個(gè)正整數(shù)和羅馬數(shù)字互相轉(zhuǎn)化的簡(jiǎn)易工具。用 Tkinter 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的羅馬數(shù)字轉(zhuǎn)化工具 一文中已經(jīng)提供了可以將正整數(shù)轉(zhuǎn)化為羅馬數(shù)字的代碼,本文會(huì)探討如何進(jìn)行將羅馬數(shù)字轉(zhuǎn)化為正整數(shù)。
正文
如何將羅馬數(shù)字轉(zhuǎn)化為正整數(shù)
轉(zhuǎn)化規(guī)則可以參考 13. 羅馬數(shù)字轉(zhuǎn)整數(shù) 這道題。以 MMMXCIV\text{MMMXCIV}MMMXCIV 為例,如果需要手動(dòng)轉(zhuǎn)化的話,可以這樣分析:將 MMMXCIV\text{MMMXCIV}MMMXCIV 視為以下三部分
- MMM:表示 3000
- XC:表示 90
- IV:表示 4
因此 MMMXCIV對(duì)應(yīng)的整數(shù)是 3000+90+4=3094。用代碼來(lái)處理時(shí),不必這么做,可以簡(jiǎn)單些 ??
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
檢查輸入是否合法
上一小節(jié)提供的 to_int 方法可以將合法的羅馬數(shù)字轉(zhuǎn)化為對(duì)應(yīng)的正整數(shù),但也要考慮到用戶的輸入可能非法。例如 IIMMM按照 to_int 方法的邏輯,會(huì)被處理成 3000,但是 IIMMM 不是合法的羅馬數(shù)字(3000對(duì)應(yīng)的羅馬數(shù)字是 MMM)。用 Tkinter 實(shí)現(xiàn)一個(gè)簡(jiǎn)單的羅馬數(shù)字轉(zhuǎn)化工具 一文提到,我們把整數(shù)轉(zhuǎn)化為羅馬數(shù)字時(shí),可以分別處理千位/百位/十位/個(gè)位,這幾位是獨(dú)立的。以個(gè)位為例,如果個(gè)位不是 000 的話,那么合法的情況只有以下 9 種
| 個(gè)位上的數(shù)字 | 對(duì)應(yīng)的羅馬數(shù)字 |
|---|---|
| 1 | I |
| 2 | II |
| 3 | III |
| 4 | IV |
| 5 | V |
| 6 | VI |
| 7 | VII |
| 8 | VIII |
| 9 | IX |
那么對(duì)應(yīng)的正則表達(dá)式可以寫成 I|II|III|IV|V|VI|VII|VIII|IX。但是這樣寫太暴力了,可以將 1,2,3的情況合并,將 5,6,7,8 的情況合并。合并后變?yōu)?I{1,3}|IV|VI{0,3}|IX,再加上個(gè)位為 000 的情況,正則表達(dá)式變?yōu)???
I{0,3}|IV|VI{0,3}|IX
用類似的思路進(jìn)行分析,可以得出合法羅馬數(shù)字對(duì)應(yīng)的“十位部分”滿足下方的正則表達(dá)式
X{0,3}|XL|LX{0,3}|XC
用類似的思路進(jìn)行分析,可以得出合法羅馬數(shù)字對(duì)應(yīng)的“百位部分”滿足下方的正則表達(dá)式
C{0,3}|CD|DC{0,3}|CM
合法羅馬數(shù)字對(duì)應(yīng)的“千位部分”滿足下方的正則表達(dá)式
M{0,3}
將以上結(jié)果合并在一起,正則表達(dá)式變?yōu)???
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)
"" 也滿足這個(gè)正則表達(dá)式,但是我們需要排除掉 ""。
完整的代碼
A First (Real) Example 一文中有使用Tkinter生成圖形化界面的簡(jiǎn)單例子。在它的基礎(chǔ)上,可以寫出以下 Python3代碼
from tkinter import *
from tkinter import ttk
import re
def convert():
try:
raw = roman.get().strip()
if raw == "":
result.set("無(wú)效輸入")
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("無(wú)效輸入")
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("羅馬數(shù)字轉(zhuǎn)整數(shù)小工具")
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="轉(zhuǎn)化為整數(shù)", command=convert).grid(column=1, row=2, sticky=W)
ttk.Label(mainframe, text="請(qǐng)輸入一個(gè)羅馬數(shù)字").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()
運(yùn)行
請(qǐng)將上一小節(jié)展示的完整代碼保存為 from_roman.py。使用如下命令可以運(yùn)行 from_roman.py
python3 from_roman.py
運(yùn)行效果如下

我們輸入一個(gè)合法的羅馬數(shù)字,例如 MCMXCVII,然后點(diǎn)擊“轉(zhuǎn)化為羅馬數(shù)字”按鈕,效果如下

再用其他羅馬數(shù)字驗(yàn)證一下(例如 MMMXCIV),效果如下

運(yùn)行結(jié)果符合預(yù)期。
以上就是Python使用Tkinter實(shí)現(xiàn)一個(gè)羅馬數(shù)字轉(zhuǎn)整數(shù)的簡(jiǎn)單工具的詳細(xì)內(nèi)容,更多關(guān)于Python Tkinter羅馬數(shù)字轉(zhuǎn)整數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python詳細(xì)對(duì)比講解break和continue區(qū)別
這篇文章主要介紹了python循環(huán)控制語(yǔ)句 break 與 continue,break就像是終止按鍵,不管執(zhí)行到哪一步,只要遇到break,不管什么后續(xù)步驟,直接跳出當(dāng)前循環(huán)2022-06-06
Python readline()和readlines()函數(shù)實(shí)現(xiàn)按行讀取文件
本文主要介紹了Python readline()和readlines()函數(shù)實(shí)現(xiàn)按行讀取文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
在服務(wù)器上運(yùn)行python文件詳細(xì)步驟
很多小伙伴想知道如何在服務(wù)器上跑python程序的方法,那么這篇文章主要給大家介紹了關(guān)于在服務(wù)器上運(yùn)行python文件的詳細(xì)步驟,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
python實(shí)現(xiàn)無(wú)邊框進(jìn)度條的實(shí)例代碼
這篇文章主要介紹了python實(shí)現(xiàn)無(wú)邊框進(jìn)度條的實(shí)例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
Pandas.DataFrame重置Series的索引index(reset_index)
本文主要介紹了Pandas.DataFrame重置Series的索引index(reset_index),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
通過(guò)Python讀取照片的Exif信息解鎖圖片背后的故事
這篇文章主要為大家介紹了通過(guò)Python讀取照片的Exif信息解鎖圖片背后的故事探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
從原理到實(shí)戰(zhàn)拆解Python Socket通信的完整指南
網(wǎng)絡(luò)通信是現(xiàn)代編程的核心能力之一,本文我們就來(lái)全方位解鎖Python Socket通信的奧秘,從基礎(chǔ)概念拆解到實(shí)戰(zhàn)代碼落地,從流程梳理到避坑指南,每一步都講透講細(xì),無(wú)論是編程新手還是需要查漏補(bǔ)缺的開發(fā)者,都能快速掌握這一核心技2026-03-03
使用python將csv數(shù)據(jù)導(dǎo)入mysql數(shù)據(jù)庫(kù)
這篇文章主要為大家詳細(xì)介紹了如何使用python將csv數(shù)據(jù)導(dǎo)入mysql數(shù)據(jù)庫(kù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-05-05
Python多線程threading創(chuàng)建及使用方法解析
這篇文章主要介紹了Python多線程threading創(chuàng)建及使用方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
詳解python如何在django中為用戶模型添加自定義權(quán)限
這篇文章主要介紹了python如何在django中為用戶模型添加自定義權(quán)限,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-10-10

