14.4. roman.py, 第 4 阶段

现在 toRoman 完成了,是开始编写 fromRoman 的时候了。感谢那个将每个罗马数字和对应整数关连的完美数据结构,这个工作不比 toRoman 函数复杂。

例 14.9. roman4.py

这个文件可以在例子目录下的 py/roman/stage4/ 目录中找到。

如果您还没有下载本书附带的样例程序, 可以 下载本程序和其他样例程序

"""Convert to and from Roman numerals"""

#Define exceptions
class RomanError(Exception): pass
class OutOfRangeError(RomanError): pass
class NotIntegerError(RomanError): pass
class InvalidRomanNumeralError(RomanError): pass

#Define digit mapping
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))

# toRoman function omitted for clarity (it hasn't changed)

def fromRoman(s):
    """convert Roman numeral to integer"""
    result = 0
    index = 0
    for numeral, integer in romanNumeralMap:
        while s[index:index+len(numeral)] == numeral: 
            result += integer
            index += len(numeral)
    return result
这和 toRoman 的工作模式很相似。你遍历整个罗马数字数据结构 (一个元组的元组),与前面不同的是不去一个个搜寻最大的整数,而是搜寻 “最大的”罗马数字字符串。

例 14.10. fromRoman 如何工作

如果你不清楚 fromRoman 如何工作,在 while 结尾处添加一个 print 语句:

        while s[index:index+len(numeral)] == numeral:
            result += integer
            index += len(numeral)
            print 'found', numeral, 'of length', len(numeral), ', adding', integer
>>> import roman4
>>> roman4.fromRoman('MCMLXXII')
found M , of length 1, adding 1000
found CM , of length 2, adding 900
found L , of length 1, adding 50
found X , of length 1, adding 10
found X , of length 1, adding 10
found I , of length 1, adding 1
found I , of length 1, adding 1
1972

例 14.11. 用 romantest4.py 测试 roman4.py 的结果

fromRoman should only accept uppercase input ... FAIL
toRoman should always return uppercase ... ok
fromRoman should fail with malformed antecedents ... FAIL
fromRoman should fail with repeated pairs of numerals ... FAIL
fromRoman should fail with too many repeated numerals ... FAIL
fromRoman should give known result with known input ... ok 
toRoman should give known result with known input ... ok
fromRoman(toRoman(n))==n for all n ... ok                  
toRoman should fail with non-integer input ... ok
toRoman should fail with negative input ... ok
toRoman should fail with large input ... ok
toRoman should fail with 0 input ... ok
这儿有两个令人激动的消息。一个是 fromRoman 对于所有有效输入运转正常,时时彩计划软件公式:至少对于你测试的已知值是这样。
第二个好消息是,完备性测试也通过了。与已知值测试的通过一起来看,你有理由相信 toRomanfromRoman 对于所有有效输入值工作正常。(尚不能完全相信,理论上存在这种可能性:toRoman 存在错误而导致一些特定输入会产生错误的罗马数字表示,并且 fromRoman 也存在相应的错误,把 toRoman 错误产生的这些罗马数字错误地转换为最初的整数。取决于你的应用程序和你的要求,你或许需要考虑这个可能性。如果是这样,编写更全面的测试用例直到解决这个问题。)

======================================================================
FAIL: fromRoman should only accept uppercase input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage4\romantest4.py", line 156, in testFromRomanCase
    roman4.fromRoman, numeral.lower())
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: InvalidRomanNumeralError
======================================================================
FAIL: fromRoman should fail with malformed antecedents
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage4\romantest4.py", line 133, in testMalformedAntecedent
    self.assertRaises(roman4.InvalidRomanNumeralError, roman4.fromRoman, s)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: InvalidRomanNumeralError
======================================================================
FAIL: fromRoman should fail with repeated pairs of numerals
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage4\romantest4.py", line 127, in testRepeatedPairs
    self.assertRaises(roman4.InvalidRomanNumeralError, roman4.fromRoman, s)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: InvalidRomanNumeralError
======================================================================
FAIL: fromRoman should fail with too many repeated numerals
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage4\romantest4.py", line 122, in testTooManyRepeatedNumerals
    self.assertRaises(roman4.InvalidRomanNumeralError, roman4.fromRoman, s)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: InvalidRomanNumeralError
----------------------------------------------------------------------
Ran 12 tests in 1.222s

FAILED (failures=4)
奇妙破解版时时彩软件 思迅软件试用版 时时彩最稳定计划软件 吉林时时彩软件下载 经纬时时彩平台
君彩时时彩软件官方 江西时时彩三星综合走势图 领航时时彩软件公式 江西时时彩软件免费版 5000本金玩时时彩稳赚
3d杀号定胆彩经网 时时彩软件计划手机版 重庆时时彩0369技巧 皇冠重庆时时彩 购买重庆时时彩软件
时时彩平台开户 银狐时时彩登录 2015年7月15日江西时时彩开奖号码 时时彩五星直选稳赚吗 内蒙古时时彩直播
甘肃十一选五开查询 贵州快三开奖结果统计 深圳风采市政设施有限公司 天津时时彩开奖数据 北京十一选五开奖时间
幸运赛车平台 安徽快3和值 内蒙古时时彩技巧稳赚 浙江福利彩票12选5 安徽快3开奖直播
梭哈玩法 中国急速赛车节scc 福建11选5几点开奖结果查询 浙江11选5开奖直播 黑龙江十一选五专家推荐预测
上海福彩 利信娱乐 云南时时彩奖项规则 云南快乐10分开奖查询 七星彩小说