我有一个将罗马数字转换为整数的程序,反之亦然。我的问题是我真的不知道如何创建一个函数来检查用户输入是否是有效的罗马数字。我的代码现在:
def checkIfRomanNumeral(numeral):
"""Controls that the userinput only contains valid roman numerals"""
numeral = numeral.upper()
validRomanNumerals = ["M", "D", "C", "L", "X", "V", "I", "(", ")"]
for letters in numeral:
if letters not in validRomanNumerals:
print("Sorry that is not a valid roman numeral")
return True
elif letters in validRomanNumerals:
romanToInt(numeral)
break
我认为现在的问题是该函数只检查输入中的第一个字母(数字),因为for循环。如果输入的任何字母不是罗马数字,有人可以帮助我使功能检查整个输入并打印(“抱歉,这不是一个有效的罗马数字”)。列表中的括号validRomanNumerals用于转换大于4000的数字,因此它们必须在那里。
答案 0 :(得分:4)
将一个转换器从一个转换器写入罗马人是一个标准的面试问题。我曾经写过以下双向实现(toString
- 十进制到罗马; parse
- 罗马到十进制)。该实施标准化了罗马数字表示的一些额外标准,这些标准不是强制性的,但通常遵循:
'''
Created on Feb 7, 2013
@author: olegs
'''
ROMAN_CONSTANTS = (
( "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" ),
( "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" ),
( "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" ),
( "", "M", "MM", "MMM", "", "", "-", "", "", "" ),
)
ROMAN_SYMBOL_MAP = dict(I=1, V=5, X=10, L=50, C=100, D=500, M=1000)
CUTOFF = 4000
BIG_DEC = 2900
BIG_ROMAN = "MMCM"
ROMAN_NOUGHT = "nulla"
def digits(num):
if num < 0:
raise Exception('range error: negative numbers not supported')
if num % 1 != 0.0:
raise Exception('floating point numbers not supported')
res = []
while num > 0:
res.append(num % 10)
num //= 10
return res
def toString(num, emptyZero=False):
if num < CUTOFF:
digitlist = digits(num)
if digitlist:
res = reversed([ ROMAN_CONSTANTS[order][digit] for order, digit in enumerate(digitlist) ])
return "".join(res)
else:
return "" if emptyZero else ROMAN_NOUGHT
else:
if num % 1 != 0.0:
raise Exception('floating point numbers not supported')
# For numbers over or equal the CUTOFF, the remainder of division by 2900
# is represented as above, prepended with the multiples of MMCM (2900 in Roman),
# which guarantees no more than 3 repetitive Ms.
return BIG_ROMAN * (num // BIG_DEC) + toString(num % BIG_DEC, emptyZero=True)
def parse(numeral):
numeral = numeral.upper()
result = 0
if numeral == ROMAN_NOUGHT.upper():
return result
lastVal = 0
lastCount = 0
subtraction = False
for symbol in numeral[::-1]:
value = ROMAN_SYMBOL_MAP.get(symbol)
if not value:
raise Exception('incorrect symbol')
if lastVal == 0:
lastCount = 1
lastVal = value
elif lastVal == value:
lastCount += 1
# exceptions
else:
result += (-1 if subtraction else 1) * lastVal * lastCount
subtraction = lastVal > value
lastCount = 1
lastVal = value
return result + (-1 if subtraction else 1) * lastVal * lastCount
答案 1 :(得分:1)
def checkIfRomanNumeral(numeral):
"""Controls that the userinput only contains valid roman numerals"""
numeral = numeral.upper()
validRomanNumerals = ["M", "D", "C", "L", "X", "V", "I", "(", ")"]
valid = True
for letters in numeral:
if letters not in validRomanNumerals:
print("Sorry that is not a valid roman numeral")
valid = False
break
return valid
返回给定的布尔值 “数字”是否为罗马数字。
答案 2 :(得分:1)
除了已经指出的设计问题外,我想回答一个问题为什么你的for-loop没有通过所有数字
如果您的代码认为条目有效,则循环进入elif
子句
它调用romanToInt(numeral)
然后调用break
。这是你的问题:break
把它解决了。
插图:在此示例中,只要条件满足,循环将停止通过i in list
for i in list:
# do something
if condition:
break # "Stop the innermost loop now!"
答案 3 :(得分:1)
您可以将输入和有效文字转换为集合,然后将它们减去:
,而不是循环def checkIfRomanNumeral(numeral):
numeral = {c for c in numeral.upper()}
validRomanNumerals = {c for c in "MDCLXVI()"}
return not numeral - validRomanNumerals
如果True
有效,则返回numeral
,否则返回False
。 (假设空字符串有效)
答案 4 :(得分:-1)
在romantoint
循环
for
def checkIfRomanNumeral(numeral):
"""Controls that the userinput only contains valid roman numerals"""
numeral = numeral.upper()
validRomanNumerals = ["M", "D", "C", "L", "X", "V", "I"]
for letters in numeral:
if letters not in validRomanNumerals:
print("Sorry that is not a valid roman numeral")
return False
romanToInt(numeral)