转换罗马/阿拉伯数字高于4000

时间:2013-12-20 11:56:49

标签: python function

我打算编写一个程序,将罗马数字转换为阿拉伯数字,反之亦然。我已经有一个工作代码,用于转换4000以下的数字。对于大于或等于4000的罗马数字,新的写法是括号表示乘以1000.所以例如4000是(IV),6010是(VI) X等感谢答案。 丹尼尔

编辑:好的,以便解决问题。没有大于3999的罗马数字,所以编写更大数字的方法是在罗马数字周围放置一个条形(或括号),这意味着数字应该乘以1000

现在的功能:

def intToRoman(integer):
    rlist = romanList = [(1000, "M"),(900, "CM"),(500, "D"),(400, "CD"),(100, "C"),(90, "XC"),(50, "L"),(40, "XL"),(10, "X"),(9, "IX"),(5, "V"),(4, "IV"),(1, "I")]
    romanResult = ""
    for wholeNumber in rlist:
            while integer >= wholeNumber[0]:
                    integer -= wholeNumber[0]
                    romanResult += wholeNumber[1]
    return romanResult

def romanToInt(numeral):
    rlist = romanList = [(1000, "M"),(900, "CM"),(500, "D"),(400, "CD"),(100, "C"),(90, "XC"),(50, "L"),(40, "XL"),(10, "X"),(9, "IX"),(5, "V"),(4, "IV"),(1, "I")]
        index = 0
        intResult = 0
        for integer, romanNumeral in rlist:
            while numeral[index : index + len(romanNumeral)] == romanNumeral:
                intResult += integer
                index += len(romanNumeral)

2 个答案:

答案 0 :(得分:1)

您可以使用divmod() function同时生成整数除数和余数:

>>> divmod(45, 10)
(4, 5)

这是4次10次,余下5次。

使用该功能,它既产生简单的罗马数字输出,又处理4000的指数的罗马数字变得更加简单。每个较高的指数都包含在增加的括号中:

romanList = [
    (1000, "M"), (900, "CM"),
    (500, "D"), (400, "CD"), 
    (100, "C"), (90, "XC"), 
    (50, "L"), (40, "XL"),
    (10, "X"), (9, "IX"),
    (5, "V"), (4, "IV"),
    (1, "I")
]

def intToRoman(integer):
    result = []
    parenscount = 0
    while integer:
        integer, num = divmod(integer, 4000)
        romanResult = ""
        for value, rchar in romanList:
            count, num = divmod(num, value)
            romanResult += count * rchar
        if romanResult:
            result.append('{}{}{}'.format(
                '(' * parenscount, romanResult, ')' * parenscount))
        parenscount += 1
    return ' '.join(result[::-1])

因为我们在result中按从小到大的顺序添加罗马数字,所以在将字符串连接在一起时,您需要在结尾处反转列表; result[::-1]使用否定步骤撤消列表。

我将romanList移动到全局,我们可以在以后将罗马数字解析回数字时重复使用它。

演示:

>>> intToRoman(2013)
'MMXIII'
>>> intToRoman(3999)
'MMMCMXCIX'
>>> intToRoman(4000)
'(I)'
>>> intToRoman(4010230)
'(MII) MMCCXXX'
>>> intToRoman(237310230)
'((XIV)) (MMMCCCXXVII) MMCCXXX'

另一方面,我们可以在每次找到右括号时将结果简化并乘以4000:

def romanToInt(numeral):
    result = 0
    while numeral:
        preparse_length = len(numeral)
        groupresult = 0
        numeral = numeral.lstrip('( ')  # remove opening parens and spaces
        for value, rchar in romanList:
            while numeral.startswith(rchar):
                groupresult += value
                numeral = numeral[len(rchar):]
        if len(numeral) == preparse_length:
            # No valid numerals found, not a Roman numeral then
            raise ValueError(
                'ValueError: invalid literal for romanToInt: {!r}'.format(numeral))
        while numeral[:1] == ')':
            groupresult *= 4000
            numeral = numeral[1:]
        result += groupresult
    return result

演示:

>>> romanToInt('MMXIII')
2013
>>> romanToInt('MMMCMXCIX')
3999
>>> romanToInt('(I)')
4000
>>> romanToInt('(MII) MMCCXXX')
4010230
>>> romanToInt('((XIV)) (MMMCCCXXVII) MMCCXXX')
237310230
>>> romanToInt('booh')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 14, in romanToInt
ValueError: ValueError: invalid literal for romanToInt: 'booh'

答案 1 :(得分:0)

您只需要两个功能。一个数字高于4000,一个数字低于数字。

def smallIntToRoman(integer):
    rlist = romanList = [(1000, "M"),(900, "CM"),(500, "D"),(400, "CD"),(100, "C"),(90, "XC"),(50, "L"),(40, "XL"),(10, "X"),(9, "IX"),(5, "V"),(4, "IV"),(1, "I")]
    romanResult = ""
    for wholeNumber in rlist:
            while integer >= wholeNumber[0]:
                    integer -= wholeNumber[0]
                    romanResult += wholeNumber[1]
    return romanResult

def bigIntToRoman(integer):
    thousands, rest = divmod(integer, 1000)
    return "({}){}".format(smallIntToRoman(thousands), smallIntToRoman(rest))

def intToRoman(integer):
    if integer >= 4000:
        return bigIntToRoman(integer)
    else:
        return smallIntToRoman(integer)


def smallRomanToInt(numeral):
    rlist = romanList = [(1000, "M"),(900, "CM"),(500, "D"),(400, "CD"),(100, "C"),(90, "XC"),(50, "L"),(40, "XL"),(10, "X"),(9, "IX"),(5, "V"),(4, "IV"),(1, "I")]
    if checkIfRomanNumeral(numeral) is False:
        pass
    elif checkIfRomanNumeral(numeral) is True:
        index = 0
        intResult = 0
        for integer, romanNumeral in rlist:
            while numeral[index : index + len(romanNumeral)] == romanNumeral:
                intResult += integer
                index += len(romanNumeral)

def romainToInt(numeral):
    if len(numeral) == 0:
        return None
    int_parts = numeral[1:].split(')') # Better done with regex
    if len(int_parts) == 1:
        return smallRomainToInt(numeral)
    elif len(int_parts) == 2:
        big = smallRomainToInt(int_parts[1])
        small = smallRomainToInt(int_parts[0])
        if big is None or small is None:
            return None
        else:
            return big * 1000 + small
    else:
        return None