检查输入是否是有效的罗马数字

时间:2014-01-07 14:00:46

标签: python python-3.x

我有一个将罗马数字转换为整数的程序,反之亦然。我的问题是我真的不知道如何创建一个函数来检查用户输入是否是有效的罗马数字。我的代码现在:

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的数字,因此它们必须在那里。

5 个答案:

答案 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)