對乙個羅馬數字與阿拉伯數字轉換演算法的分析

2021-06-27 23:09:17 字數 2760 閱讀 9273

在看《dive into python》的單元測試時,發現用作例子的「阿拉伯數字-羅馬數字」的轉換演算法非常的巧妙,現在發上來和大家分享一下。

romannumeralmap = (('m',1000),

('cm',900),

('d',500),

('cd',400),

('c',100),

('xc',90),

('l',50),

('xl',40),

('x',10),

('ix',9),

('v',5),

('iv',4),

('i',1))

def toroman(n):

result = ""

for numeral, integer in romannumeralmap:

while n >= integer:

result += numeral

n -= integer

return result

def fromroman(s):

result = 0

index = 0

for numeral, integer in romannumeralmap:

while s[index:index+len(numeral)] == numeral:

result += integer

index += len(numeral)

return result

print toroman(1356)

print fromroman('mcmlxxii')

這個演算法的聰明之處,就在於他通過乙個romannumeralmap,把羅馬數字與阿拉伯數字裡面的「邊界值」做出一一對應。這個邊界剛剛好是羅馬數字組合之間的轉換。例如,i,ii,iii都可以通過第乙個邊界值組合獲得;v,vi,vii,viii可以通過v和i的組合獲得。而對於一些特殊的值,則直接列出來。例如iv。通過這個邊界值的組合,就能實現所需求的轉換。這就類似於在一些機讀卡上,需要填寫1到100的數字,他會使用0,1,2,4,7這樣以來:

3 = 1 + 2;

5 = 4 + 1;

6 = 4 + 2;

8 = 7 + 1;

9 = 7 + 2.

首先看一下toroman()函式,把阿拉伯數字轉換成羅馬數字。它使用python連線字串的操作符號 + 來使「邊界值」連線到一起。例如用作例子的n = 1356,程式遍歷romannumeralmap,尋找n對應的羅馬數字,如果找不到,那就找剛剛比n小一點的數字對應的羅馬字元。遍歷在能使n 在romannumeralmap有對應值時結束。

找到剛剛比1356小的那個值對應的羅馬數字,也就是1000,m

再繼續找剛剛比n = 1356 - 1000 = 356小的數,也就是100,c;

又繼續找比n = 356 - 100 = 256小的數,還是100,也就是c;

再找比n = 256 - 100 = 156小的數,仍然是100,c;

繼續找比n = 156 - 100 = 56 小的數,50,l;

繼續找比n = 56 - 50 = 6小的數,5,v;

繼續找n = 6 - 5 = 1對於的數,1,i。 結束。

所以1356對應的值為mccclvi。 這樣的操作很類似於在十進位制裡面,乙個數字1356 = 1000 + 300 + 50 + 6,只是阿拉伯數字裡面6是乙個單獨的符號,而羅馬數字裡面vi是個v + i的組合而已。

下面再說說fromroman()函式,把羅馬數字轉換成阿拉伯數字。這個函式在理解上面可能比toroman()稍稍要困難一點。

還是用例子來說明,mcmlxxii轉換成阿拉伯數字。其中如下**

s[index:index+len(numeral)]
作用是把字串s中,從第index位到第index+ len(numeral)位(不包含第index + len(numeral)位自身)的字元提取出來。比如:

>>> a = 'helloworld'

>>> print a[2:5]

llo

即s的第2,3,4位被取出。

回到對s = 'mcmlxxii'的處理。

首先map中第乙個羅馬字元是m,只有一位,就把s 的第0位拿出來對比,發現s的第0位剛剛好是m,於是得到乙個1000,index變為1,則之後從s的第一位開始。簡單的說,相當於s 變成了s = 'cmlxxii'

接下來,經過一些無效的值以後,輪換到cm,發現cm為兩位,就取出s的前兩位,也就是cm,發現在s中剛剛好有cm,於是得到900. index再加2,則實際上s就相當於變成了lxxii

繼續經過一些無效值以後,輪換到了l,發現s當前的1位為l,於是在map中有對應的值50.然後index加1,s相當於變成了xxii

接下來到了x,發現s當前的1位為x,在map中有對應的值10.然後index 再加1,s變成了xii

雖然這個時候人已經知道是12了,但是計算機還是不知道,於是繼續乙個x,s變為ii

然後出現乙個i,s變為i

終於程式找到了乙個直接相等的值i,於是轉換結束。

所以mcmlxxii對於的阿拉伯數字是1000+900+50+10+10+1+1 = 1972

這個方法,把乙個羅馬數字從高位開始逐次剝離最高位,從而漸漸的把數字縮小。

最近正在學習演算法。因為越來越發現現在做的東西,如果僅僅實現功能的話,效能會出現瓶頸。希望我以後能寫出更好的演算法。

羅馬數字轉換阿拉伯數字0 3999

有兩條須注意掌握 1.基本數字 x c 中的任何乙個 自身連用構成數目 或者放在大數的右邊連用構成數目 都不能超過三個 放在大數的左邊只能用乙個 2.不能把基本數字 v l d 中的任何乙個作為小數放在大數的左邊採用相減的方法構成數目 放在大數的右邊採用相加的方式構成數目 只能使用乙個 基本字元 i...

阿拉伯數字轉羅馬數字

最開始想的是當成進製轉,比如說 1 i,2 ii,5 v,6 vi public static string inttoroman1 int num int radix stringbuffer sb new stringbuffer for int i radix.length 1 i 0 i r...

阿拉伯數字轉羅馬數字

時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld 題目描述 張老師需要用數字來統計學生們的得分情況,但阿拉伯數字已經不能滿足他的要求了,所以想請你幫忙將學生的成績轉換成羅馬數字。羅馬數字是由七個不同的符號來表示 i...