Roman Numerals to Integers Converter with Python using a dictionary
我正在学习编码,我做了一个练习,把罗马数字转换成整数。我知道写这个程序有很多不同的方法,但如果你能帮我找出错误,我会很感激的。我很想听听关于如何写得更好的建议,但我现在真正能使用的是理解我对这本书的错误之处。
我有一本叫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | roman_numerals = {"M":1000,"CM":900,"D":500,"CD":400,"C":100,"XC":90,"L":50,"XL":40,"X":10,"V":5,"IV":4,"I":1} def roman_int(user_choice): if user_choice =="1": user_roman = input("What numeral would you like to convert? ").upper() resultI = 0 for k,v in roman_numerals.items(): if user_roman == k: resultI += roman_numerals.get(user_roman) else: for i in user_roman: if i in roman_numerals.keys(): if i == k: resultI += v print(resultI) |
当我运行代码时,如果我使用的数字等于一个以上字符的
谢谢您!
最好将值表示为元组列表,因为这样可以定义其中的顺序,因此,如果字符串在该点包含
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | roman_numerals = [ ('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) ] |
请注意,您忘记使用
现在我们可以通过每次执行
1 2 3 4 5 6 7 8 9 10 11 12 | def roman_int(user_choice): ix = 0 result = 0 while ix < len(user_choice): for k, v in roman_numerals: if user_choice.startswith(k, ix): result += v ix += len(k) break else: raise ValueError('Invalid Roman number.') return result |
。
因此,我们通过字符串进行枚举,并且每次查找匹配的罗马数字。例如:
1 2 3 4 5 6 | >>> roman_int('MCMXC') 1990 >>> roman_int('MCMXCIII') 1993 >>> roman_int('MMXVIII') 2018 |
。
例如,如果输入无效字符,系统也会出错:
1 2 3 4 5 | >>> roman_int('MMXQVIII') Traceback (most recent call last): File"<stdin>", line 1, in <module> File"<stdin>", line 11, in roman_int ValueError: Invalid Roman number. |
不过,上述方法并不十分有效:每次我们枚举
1 2 3 4 5 6 7 8 9 10 11 12 13 | def roman_int(user_choice): ix = 0 iy = 0 result = 0 while ix < len(user_choice): while iy < len(roman_numerals) and not user_choice.startswith(roman_numerals[iy][0], ix): iy += 1 if iy < len(roman_numerals): result += roman_numerals[iy][1] ix += len(roman_numerals[iy][0]) else: raise ValueError('Invalid Roman numeral') return result |
。
这再次产生了我们预期的结果:
1 2 3 4 5 6 7 8 9 10 | >>> roman_int('MDCCLXXVI') 1776 >>> roman_int('MCMLIV') 1954 >>> roman_int('MCMXC') 1990 >>> roman_int('MMXIV') 2014 >>> roman_int('MMXVIII') 2018 |
但也更严格,例如,
1 2 3 4 5 6 7 | >>> roman_int('CMM') Traceback (most recent call last): File"<stdin>", line 1, in <module> File"<stdin>", line 12, in roman_int ValueError: Invalid Roman numeral >>> roman_int('MCM') 1900 |
。
您必须确保使用了构成总和的所有字符。由于所有多字符的"原子"字都以较低值的单位开始,否则,较高值的单位首先出现,因此一个简单的贪婪方法是可行的:
- 尝试将前两个字符转换为一个整体,如果不可能,请转换第一个单个字符。
向前移动适当数量的步骤。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19def roman_int(user_roman):
user_roman = user_roman.upper()
resultI = 0
while user_roman:
# try first two chars
if user_roman[:2] in roman_numerals:
resultI += roman_numerals[user_roman[:2]]
# cut off first two chars
user_roman = user_roman[2:]
# try first char
elif user_roman[:1] in roman_numerals:
resultI += roman_numerals[user_roman[:1]]
# cut off first char
user_roman = user_roman[1:]
else:
print('No roman number')
return
print(resultI)
不需要循环查字典。我的代码稍有不同,但我已经尽力保留尽可能多的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | roman_numerals = {"M":1000,"CM":900,"D":500,"CD":400,"C":100,"XC":90,"L":50,"XL":40,"X":10,"V":5,"IV":4,"I":1} def roman_int(user_choice): if user_choice =="1": user_roman = input("What numeral would you like to convert? ").upper() result = 0 values = [] # return the result if the input is in the dictionary try: result = roman_numerals[user_roman] except KeyError: # split up the user input and convert each character into corresponding numeral for i in user_roman: try: value = roman_numerals[i] values.append(value) # if user enters character not used in roman numerals except KeyError: print("Not valid input") # loop through all values and add them up for i, value in enumerate(values): try: # if a value is larger than the next value, add it if value > values[i+1]: result += value # else the number is obtained by substracting the smaller value from the larger value else: actual_value = values[i+1] - value result = result + actual_value #set the next number to 0 as it has already been added values[i+1] = 0 except IndexError: # this try except block catches the IndexError exception caused when i+1 > len(values) pass print(result) |
。
计算字符串中每个数字的出现次数,而不是检查字符串的出现次数,然后只需删除出现双字母(如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | roman_numerals = {"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 roman_int(user_choice): if user_choice =="1": result = 0 user_roman = input("What numeral would you like to convert? ").upper() for k,v in roman_numerals.items(): result += v * user_roman.count(k) if len(k) == 2: result -= roman_numerals[k[0]] * user_roman.count(k) result -= roman_numerals[k[1]] * user_roman.count(k) print(result) roman_int("1") |
另一种看问题的方法,我想
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | roman_numerals = {"M":1000,"CM":900,"D":500,"CD":400,"C":100,"XC":90,"L":50,"XL":40,"X":10,"V":5,"IV":4,"I":1} def roman_int(user_choice): if user_choice =="1": user_roman = input("What numeral would you like to convert? ").upper() resultI = 0 pos = 0 try: resultI = roman_numerals[user_roman] except: try: while pos < len(user_roman): resultI += roman_numerals[user_roman[pos]] pos+=1 except: print('Not present in our dictionary') print(resultI) |
号