<< 靈 4 � HTML 庚靴 � 量 쇰 刷 >>

靈 5 �. 傑� �맑�

5.1. ヴ健�� ��≠�

健 � �읒밀, �靴ュ “ヴ健�� ��≠밀” 曳閻�劍頌 ��況 ��숩� �도刷健� 횰靴 健��淞� �悚�윔ヴ. 健靈 윈壽솥鋼 �靴�읒 �健�槪 ≠�∽ ��劍�頌, �靴ュ 딘頌 둥껍≠ 그 ��≠ 虔뭡�� ��(before) ���槪 �� 숩∫ヴ.

健 �읒밀 �靴ュ 頌譁 밝腱頌쇰� 그靴� 頌譁밝腱頌 순橒�ュ 傑�靴� 裔�槪 虔뭡�淞� �ヴ. 玗맸 윈壽솥健 乾���ュ 鰥�ヴ� ���도, 윈壽솥鋼 솥�尤 頌譁 밝腱�槪 숩뀜槪 ↔健ヴ. 윈壽솥鋼 읫甦들 윳優寧 �屬�懊 �읒밀 손��靴 ��槪 숩뀜槪 ↔健ヴ ( “Copyright 1946”��읒 “Copyright MCMXLVI”槪 ), 玗鋼 도밀�健寧 玗鋼 ��� 셧� 섀읒밀 ( “established 1888” ��읒 “established MDCCCLXXXVIII” )槪 숩뀜劍靴�. �� 윈壽솥鋼 그↔�槪 ���刷 그靴� �� �獵밀읒밀 숩뀜槪 �도 �ヴ. 그↔鋼 밝腱 ��� 맸맑�劍頌밀 ��頌 �만頌 이�≠ 頌譁 맸�읒 �靈頌 ����ヴ (��읒밀 그 健華健 傑甦�ヴ).

頌譁 밝腱읒밀ュ, 7⌒� 珞腱≠ ��밀 윈壽≠� 籃�劍頌 �손�� 獵��� 밝腱�槪 ���ヴ.

  1. I = 1
  2. V = 5
  3. X = 10
  4. L = 50
  5. C = 100
  6. D = 500
  7. M = 1000

頌譁 밝腱況 깬뭡�ュ뎬ュ �≠� 깍�健 �ヴ:

  1. 珞腱�鋼 쇰≠�健ヴ. I1健�, II2健�, 그靴� III3健ヴ. VI6健� (珞腱�劍頌, “51”), VII7健�, 그靴� VIII8健ヴ.
  2. 10 �胛� 珞腱� (I, X, C, 그靴� M)鋼 3 纜�� �손� � �ヴ. 4읒밀, 윈壽솥鋼 그 ヴ舡� ≠� �鋼 5 腱靴 珞腱頌쇰� 홉꺌 �ヴ. 윈壽솥鋼 4IIII頌 寧�冷 � 꼬ヴ; ��읒, 그↔鋼 IV頌 寧�蘆� 玲ヴ (“5숩ヴ 1 虔ヴ”). 40XL頌 꼈윈玲ヴ (“50숩ヴ 10虔ヴ”), 41XLI頌, 42XLII頌, 43XLIII劍頌, 그靴� 44ュ (“50숩ヴ 10虔�, 그靴� 5숩ヴ 1虔劍�頌”) XLIV頌 꼈윈玲ヴ.
  3. �며�∽, 9읒밀, 윈壽솥鋼 그 ヴ舡� ≠� �鋼 10腱靴 珞腱頌 쇰� 홉꺌 �ヴ: 8VIII健ヴ, 그壽寧 9ュ (“10숩ヴ 1 虔劍�頌”) IX健�, VIIII≠ 껍レヴ (���� I 珞腱ュ 4 纜 �손� � 꼬� ┐珞健ヴ). 90XC健ヴ, 900CM健ヴ.
  4. 5 腱靴 珞腱�鋼 �손� � 꼬ヴ. 10VV≠ 껍レ� �� X頌 ��들ヴ. 100鋼 �� C健�, 據�頌 LL健 껍レヴ.
  5. 頌譁 밝腱ュ �� 胛읒밀 껍甦頌, 그靴� 잗臆읒밀 읫患臆劍頌 꼈윈玲ヴ, 그甦밀 珞腱� 뮈밀ュ ��尤 燁��ヴ. DC600健ヴ; CDュ 잽�尤 ヴ患 밝腱健ヴ (400乾뎬, “ 500 숩ヴ 100 虔ヴ ”). CI101健ヴ; ICュ 傑湧� 頌譁 밝腱獵量도 껍レヴ (���� 윈壽솥鋼 1100劍頌 쇰� 曳閻�劍頌 횹�도 꼬� ┐珞健ヴ; 윈壽솥鋼 그↔槪 XCIX頌 �꺌 ��도 匯患ヴ (“ 100숩ヴ 10虔�, 그靴� 10숩ヴ 1 虔劍�頌”).

健壽� 깍��槪 숩� � 皇鋼 �藜�ュ ���槪 ��� � �ヴ:

  1. 밝腱 �寧況 頌譁 밝腱頌 寧�蘆ュ 뎬읒ュ 읫曳 �⌒� 穢蟯� 籃輛梟健 �ヴ.
  2. 그 을도 을맸 �健ヴ: 梟� 件蘇� 珞腱읽健 傑湧� 頌譁 밝腱��, 그↔鋼 읫曳 �寧� 밝腱梟槪 寧�恬ヴ (�, ヴ맸 恍�� 그↔鋼 읫曳 � ≠� 籃�劍頌梟 居� � �ヴ).
  3. 靈�들 �胛� 밝腱�梟健 頌譁 밝腱頌 ��� � �ヴ, �尤 1 읒밀 3999��. (頌譁乾�鋼 � ≠�� 籃輛劍頌 � � 밝腱�槪 ���ュ뎬, 잇況 �� � 밝腱� 胛읒 恢�況 그� �舡劍頌� 그 穢�� 』鋼 1000劍頌 ��葉꺌 �ヴュ ↔槪 寧�蘆�ヴ, 그壽寧 �靴ュ 그↔槪 ヴ��ュ 꿩槪 ↔健ヴ. 健 �� ��槪 胛�윈, 頌譁 밝腱�鋼 1읒밀 3999�� ヴ� ↔健ヴ.)
  4. 0鋼 頌譁 밝腱읒밀 ��� 籃輛健 꼬ヴ. (�┸∽도, �� 頌譁乾�鋼 0槪 밝腱頌 휸、�ュ ⌒�健 꼬�ヴ. 밝腱�鋼 윈壽솥健 ≠�� �ュ 蘿�槪 뭐� 胛� ↔健�ヴ; 윈壽솥鋼 ≠�� �� 꿩鋼 ↔槪 �┍∽ 뭐∫ュ≠?)
  5. 頌譁 밝腱읒ュ 舡�況 ��� 籃輛健 꼬ヴ.
  6. 頌譁 밝腱읒ュ 뱉�寧 솥�況 ��� 籃輛健 꼬ヴ.

健壽� 匯� ↔健 �靈 ��, 頌譁밝腱頌 그靴� 頌譁밝腱頌쇰� 순橒�ュ ��� 匯巾읒밀 �靴ュ 朗�槪 잇�� � �ュ≠?

roman.py� �깬獵�

  1. toRoman1읒밀 3999�� 匯� 穢�읒 �� 頌譁 밝腱� ��槪 �橒�꺌 �ヴ.
  2. toRoman1읒밀 3999�� �胛 黎� 穢�≠ ���� ���꺌 �ヴ.
  3. toRoman鋼 �-穢� 뱉�≠ ���� ���꺌 �ヴ.
  4. fromRoman鋼 傑湧� 頌譁 밝腱況 ��꺌 �� 그↔健 ���ュ 밝腱況 �橒�꺌 �ヴ.
  5. fromRoman鋼 朗湧� 頌譁 밝腱≠ ���� ���꺌 �ヴ.
  6. 梟� 윈壽솥健 밝腱況 ���, 그↔槪 頌譁 밝腱頌 순橒맸��, 그靴� 寧밀 그↔槪 ヴ맸 밝腱頌 순橒��, 윈壽솥鋼 윈壽솥健 맸虔� 그 밝腱頌 怒寧꺌梟 �ヴ. 그甦밀 1..3999�健� 匯� n읒 ��윈 fromRoman(toRoman(n)) == n健ヴ.
  7. toRoman鋼 �� 頌譁 밝腱況 �珞腱況 ���윈 �橒�윈꺌 �ヴ.
  8. fromRoman鋼 읫曳 �珞腱況 頌譁 밝腱頌 ���ヴ. (� ヴ맸 恍��, 뱉珞腱≠ ��玲ヴ� ���꺌 �ヴ).

� 居�꺌 � ↔

5.2. romantest.py況 뱉⌒��

健靈 �靴ュ 잽��∽ �靴� 순橒 ��頌쇰� 잇�� � �ュ �胛況 穢��윔劍�頌, �靴ュ �。鋼 잇�� 鰥� �┱ ↔�槪 �淞� �ヴ: �靴ュ �맑� 匯딕槪 虔뭡�윈 健壽� ���健 腱�� 굶槪 ≠도刷 �� �靴≠ 읏�ュ �頌 그�健 �曳健ュ ↔槪 蟯乾�淞� �ヴ. 윈壽솥健 居鋼 �頌ヴ: �靴ュ ���� 虔뭡�� 꿩뀜タ �맑� ��況 虔뭡�淞� �ヴ.

健↔槪 傑� �맑��� 쇰花ュ뎬, ���� 듬 ⌒� 순橒 ���� 匯巾健, �ヴ� �頌그少劍頌쇰� 솥靴��葉, 傑�劍頌 虔뭡���� �맑� � � �� ┐珞健ヴ. 傑�鋼 健�읒 그 � �頌그少� 件 쇰솥健 � ↔健ヴ. �健�鋼 傑� �맑�況 胛� �屬巾��況 ≠�� �ヴ, 그 �據� 健華�∽ unittest�ュ 匯�槪 ≠玲ヴ.

Note
unittestュ �健� 2.1 健�읒밀 ��≠��ヴ. �健� 2.0 ��腱ュ 그↔槪 pyunit.sourceforge.net頌쇰� 蘆淞良槪 ��ヴ.

傑� �맑�ュ �譴 �맑�-燁� ⌒烙 �簫� ≠� 燁�� 쇰솥健ヴ. 梟� 윈壽솥健 傑� �맑�況 虔뭡�ヴ�, 그↔�槪 횰靴 虔뭡�ュ ↔健 燁��ヴ (�尤 그�健 �맑�� ��況 虔뭡�� �健 �� 霓ヴ ), 그靴� ��잴 �깬��健 순�읒 ��밀 그↔�槪 �뱃�윈 ″���. 傑� �맑�ュ �-�影� ��� 玗鋼 맸맑� �맑�況 胛� �譴蘿健 껍レヴ , 읫尤淞 그↔鋼 匯� ⌒烙� 균�읒밀 燁��ヴ:

健↔鋼 頌譁 밝腱 순橒 ���槪 胛� 잽�� �맑� 匯딕健ヴ, 그↔�鋼 껍曳 虔뭡�� 꿩뀜�梟 �균 roman.py읒 꼈윈�∽ � ↔健ヴ. �┍∽ 그 匯� ↔�健 獵潢� �ュ 曳閻�劍頌 ��� 숩健�ュ 꿩ュヴ; 健壽� �甦맑 玗鋼 回��燁 �ニ ↔도 ヴ患 ↔槪 �獵�� 꿩ュヴ. 健壽� ↔읒ュ 潔솥� 健傑≠ �劍�, 그↔槪 �靴ュ 兩∽ �� 섰 ↔健ヴ.

Example 5.1. romantest.py

윈壽솥健 껍曳 그峀∽ �� 鰥�ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

"""Unit test for roman.py"""

import roman
import unittest

class KnownValues(unittest.TestCase):
    knownValues = ( (1, 'I'),
                    (2, 'II'),
                    (3, 'III'),
                    (4, 'IV'),
                    (5, 'V'),
                    (6, 'VI'),
                    (7, 'VII'),
                    (8, 'VIII'),
                    (9, 'IX'),
                    (10, 'X'),
                    (50, 'L'),
                    (100, 'C'),
                    (500, 'D'),
                    (1000, 'M'),
                    (31, 'XXXI'),
                    (148, 'CXLVIII'),
                    (294, 'CCXCIV'),
                    (312, 'CCCXII'),
                    (421, 'CDXXI'),
                    (528, 'DXXVIII'),
                    (621, 'DCXXI'),
                    (782, 'DCCLXXXII'),
                    (870, 'DCCCLXX'),
                    (941, 'CMXLI'),
                    (1043, 'MXLIII'),
                    (1110, 'MCX'),
                    (1226, 'MCCXXVI'),
                    (1301, 'MCCCI'),
                    (1485, 'MCDLXXXV'),
                    (1509, 'MDIX'),
                    (1607, 'MDCVII'),
                    (1754, 'MDCCLIV'),
                    (1832, 'MDCCCXXXII'),
                    (1993, 'MCMXCIII'),
                    (2074, 'MMLXXIV'),
                    (2152, 'MMCLII'),
                    (2212, 'MMCCXII'),
                    (2343, 'MMCCCXLIII'),
                    (2499, 'MMCDXCIX'),
                    (2574, 'MMDLXXIV'),
                    (2646, 'MMDCXLVI'),
                    (2723, 'MMDCCXXIII'),
                    (2892, 'MMDCCCXCII'),
                    (2975, 'MMCMLXXV'),
                    (3051, 'MMMLI'),
                    (3185, 'MMMCLXXXV'),
                    (3250, 'MMMCCL'),
                    (3313, 'MMMCCCXIII'),
                    (3408, 'MMMCDVIII'),
                    (3501, 'MMMDI'),
                    (3610, 'MMMDCX'),
                    (3743, 'MMMDCCXLIII'),
                    (3844, 'MMMDCCCXLIV'),
                    (3888, 'MMMDCCCLXXXVIII'),
                    (3940, 'MMMCMXL'),
                    (3999, 'MMMCMXCIX'))

    def testToRomanKnownValues(self):
        """toRoman should give known result with known input"""
        for integer, numeral in self.knownValues:
            result = roman.toRoman(integer)
            self.assertEqual(numeral, result)

    def testFromRomanKnownValues(self):
        """fromRoman should give known result with known input"""
        for integer, numeral in self.knownValues:
            result = roman.fromRoman(numeral)
            self.assertEqual(integer, result)

class ToRomanBadInput(unittest.TestCase):
    def testTooLarge(self):
        """toRoman should fail with large input"""
        self.assertRaises(roman.OutOfRangeError, roman.toRoman, 4000)

    def testZero(self):
        """toRoman should fail with 0 input"""
        self.assertRaises(roman.OutOfRangeError, roman.toRoman, 0)

    def testNegative(self):
        """toRoman should fail with negative input"""
        self.assertRaises(roman.OutOfRangeError, roman.toRoman, -1)

    def testDecimal(self):
        """toRoman should fail with non-integer input"""
        self.assertRaises(roman.NotIntegerError, roman.toRoman, 0.5)

class FromRomanBadInput(unittest.TestCase):
    def testTooManyRepeatedNumerals(self):
        """fromRoman should fail with too many repeated numerals"""
        for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):
            self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)

    def testRepeatedPairs(self):
        """fromRoman should fail with repeated pairs of numerals"""
        for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
            self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)

    def testMalformedAntecedent(self):
        """fromRoman should fail with malformed antecedents"""
        for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
                  'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
            self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)

class SanityCheck(unittest.TestCase):
    def testSanity(self):
        """fromRoman(toRoman(n))==n for all n"""
        for integer in range(1, 4000):
            numeral = roman.toRoman(integer)
            result = roman.fromRoman(numeral)
            self.assertEqual(integer, result)

class CaseCheck(unittest.TestCase):
    def testToRomanCase(self):
        """toRoman should always return uppercase"""
        for integer in range(1, 4000):
            numeral = roman.toRoman(integer)
            self.assertEqual(numeral, numeral.upper())

    def testFromRomanCase(self):
        """fromRoman should only accept uppercase input"""
        for integer in range(1, 4000):
            numeral = roman.toRoman(integer)
            roman.fromRoman(numeral.upper())
            self.assertRaises(roman.InvalidRomanNumeralError,
                              roman.fromRoman, numeral.lower())

if __name__ == "__main__":
    unittest.main()   

� 居�꺌 � ↔

5.3. 뭡×槪 胛� �맑�

傑� �맑�� ≠� �셜�乾 쇰솥鋼 ⌒샥�乾 �맑� �健맑況 깬뭡�ュ ↔健ヴ. �寧� �맑� �健맑ュ �맑��� �ュ 그 ��읒 �� � ⌒� �珞읒 �� 影ヴ.

�맑� �健맑ュ ....況 � � ��꺌 �ヴ

健↔槪 �靈頌 �윈, �靴� 憬 纜櫻 �맑� �健맑況 깬��숩腱. �靴ュ ヴ舡�  鋼 �깬獵�槪 ≠玲ヴ:

  1. toRoman1읒밀 3999��� 匯� 穢�읒 ��윈 頌譁 밝腱 ��槪 �橒�꺌 �ヴ.

Example 5.2. testToRomanKnownValues

class KnownValues(unittest.TestCase):
1
    knownValues = ( (1, 'I'),
                    (2, 'II'),
                    (3, 'III'),
                    (4, 'IV'),
                    (5, 'V'),
                    (6, 'VI'),
                    (7, 'VII'),
                    (8, 'VIII'),
                    (9, 'IX'),
                    (10, 'X'),
                    (50, 'L'),
                    (100, 'C'),
                    (500, 'D'),
                    (1000, 'M'),
                    (31, 'XXXI'),
                    (148, 'CXLVIII'),
                    (294, 'CCXCIV'),
                    (312, 'CCCXII'),
                    (421, 'CDXXI'),
                    (528, 'DXXVIII'),
                    (621, 'DCXXI'),
                    (782, 'DCCLXXXII'),
                    (870, 'DCCCLXX'),
                    (941, 'CMXLI'),
                    (1043, 'MXLIII'),
                    (1110, 'MCX'),
                    (1226, 'MCCXXVI'),
                    (1301, 'MCCCI'),
                    (1485, 'MCDLXXXV'),
                    (1509, 'MDIX'),
                    (1607, 'MDCVII'),
                    (1754, 'MDCCLIV'),
                    (1832, 'MDCCCXXXII'),
                    (1993, 'MCMXCIII'),
                    (2074, 'MMLXXIV'),
                    (2152, 'MMCLII'),
                    (2212, 'MMCCXII'),
                    (2343, 'MMCCCXLIII'),
                    (2499, 'MMCDXCIX'),
                    (2574, 'MMDLXXIV'),
                    (2646, 'MMDCXLVI'),
                    (2723, 'MMDCCXXIII'),
                    (2892, 'MMDCCCXCII'),
                    (2975, 'MMCMLXXV'),
                    (3051, 'MMMLI'),
                    (3185, 'MMMCLXXXV'),
                    (3250, 'MMMCCL'),
                    (3313, 'MMMCCCXIII'),
                    (3408, 'MMMCDVIII'),
                    (3501, 'MMMDI'),
                    (3610, 'MMMDCX'),
                    (3743, 'MMMDCCXLIII'),
                    (3844, 'MMMDCCCXLIV'),
                    (3888, 'MMMDCCCLXXXVIII'),
                    (3940, 'MMMCMXL'),
                    (3999, 'MMMCMXCIX'))                        2

    def testToRomanKnownValues(self):                           3
        """toRoman should give known result with known input"""
        for integer, numeral in self.knownValues:
            result = roman.toRoman(integer)                     4 5
            self.assertEqual(numeral, result)                   6
1 �맑� �健맑況 虔뭡�� 胛�밀, 憬 纜櫻 � 件鋼 unittest 匯�� TestCase �甦맑況 �쇰�甦맑優 �ュ ↔健ヴ. 健 �甦맑ュ 皇鋼 傑�� 回��≠ ��밀 윈壽솥� �맑� �健맑읒 그↔槪 ���윈 윈壽솥鋼 �샥� 獵��槪 �맑�� � �ヴ.
2 健↔鋼 蘆≠ �돛劍頌 蟯乾� 穢�/밝腱 �� 靴맑�健ヴ. 그↔읒ュ ≠� 賂鋼 10 ⌒� 밝腱, ≠� �鋼 밝腱, �⌒�-珞腱頌 들, 頌譁 밝腱頌 순橒�ュ 匯� 밝腱, 그靴� 朗虔胛頌 흡鋼 ヴ患 傑湧� 밝腱�健 ��들ヴ. 傑� �맑�� �瑩鋼 建悚 ≠�� 匯� ↔槪 �맑��ュ ↔健 껍レ�, ���乾 ��槪 �맑��ュ ↔健ヴ.
3 匯� ⌒샥�乾 �맑�ュ 腱� 腱�� 回��健ヴ, 그↔鋼 껍朗塑 乾�도 �橒 』도 ≠�� 꿩ュヴ. 梟� 그 回��≠ 잇�況 烙휸맸�� 꿩� 穢��劍頌 梧��ヴ�, 그 �맑�ュ ��들 ↔劍頌 。�들ヴ; 梟件 그 回��≠ 잇�況 件劍��, 그 �맑�ュ ��� ↔劍頌 。�들ヴ.
4 윈�읒밀 �靴ュ 그 �靈� toRoman ��況 繇��ヴュ ↔槪 ����. (腱, 그 ��ュ 껍曳 虔뭡�� 꿩뀜ヴ, 그壽寧 虔뭡��ヴ�, 健 �乾읒밀 力頌 그↔槪 繇�� ↔健ヴ.) �靴ュ �� toRoman ��況 胛� API況 穢��윔ヴ: 그↔鋼 (순橒�꺌� 밝腱乾) � ⌒� 穢�況 ��꺌梟 �ヴ 그靴� (頌譁 밝腱 ��) 珞腱읽槪 �橒�꺌 �ヴ. 梟� API ≠ 그↔� ヴ花ヴ�, 健 �맑�ュ ��� ↔劍頌 。�들ヴ.
5 �� ��� ↔鋼 �靴ュ toRoman槪 繇�� ┐ �─� 잇�도 擄껍 梗� 꿩ュヴュ ↔健ヴ. 健↔鋼 �도�健ヴ. �靴≠ 그↔槪 傑湧� 建悚劍頌 繇�� ┐, toRoman鋼 잇�況 烙휸맸�밀ュ 꿴들ヴ 그靴� 健壽� 建悚 』�鋼 匯듬 傑湧�ヴ. 梟� toRoman健 잇�況 件劍�ヴ�, 健 �맑�ュ ��� ↔劍頌 。��ヴ.
6 toRoman ��ュ 穢蟯�∽ 穢���倪�, 穢蟯�∽ 繇���劍�, 뭡×�劍頌 잽���, 그靴� �寧� 』槪 �橒�ヴ� ≠穢�숩腱, ≠� 譁�恢 ��ュ 그 ��≠ �橒� 』健 �鋼 (right) 』乾≠況 瑩↑�ュ ↔健ヴ. 健↔鋼 �� �珞健ヴ, 그靴� TestCase �甦맑ュ 回��, assertEqual況 靈×�ュ뎬, 듬 ⌒� 』健  鋼≠況 瑩↑�ヴ. 梟� toRoman劍頌쇰� �橒들 그 ��(result)≠ �靴≠ 잇��� �ュ 그 꿱淞玲 』(numeral)� 件��� 꿩ュヴ�, assertEqualュ 잇�況 件劍� ↔健� 그 �맑�ュ ��� ↔健ヴ. 梟� 듬 ⌒� 』健  ヴ�, assertEqualュ 껍朗↔도 �� 꿩槪 ↔健ヴ. 梟� toRoman劍頌쇰� �橒들 匯� 』健 �靴≠ 잇�� 그 꿱淞玲 』�  ヴ�, assertEqualュ 據�頌 잇�況 件劍�� 꿩ュヴ, 그甦밀 testToRomanKnownValuesュ �균 穢��劍頌 暎��ヴ, 그↔鋼 toRoman健 健 �맑�況 ���윔ヴュ ↔槪 �藜�ヴ.

5.4. ��況 胛� �맑�

�靴� ��≠ 霓鋼 建悚健 ��� ┐ 뭡×�ュ ↔槪 �맑��ュ ↔梟劍頌ュ 潔솥�� 꿩ヴ; �靴ュ �� 寧흴 建悚健 ��� ┐ 그↔�健 ���ヴュ ↔槪 �맑� �꺌 �ヴ. 그靴� �� �┱ 暎�� ��≠ 껍レ�; 그↔�鋼 �靴≠ 잇�� 籃��頌 ���꺌�ヴ.

toRoman況 胛� �靴� ヴ患 �깬 獵�槪 ���� :

  1. toRoman1읒밀 3999��� �胛 黎읒 �ュ 穢�≠ ��玲ヴ� ���꺌 �ヴ.
  2. toRomanュ �-穢� 뱉�≠ ���� ���꺌 �ヴ.

�健�읒밀, ��ュ 잇�況 件劍�劍頌�, ��況 寧�恬ヴ 그靴� unittest 匯�鋼, ��≠ 寧흴 建悚』健 ���� �샥� 잇�況 件劍�ュ� �맑�況 �� 胛� 回��況 靈×�ヴ.

Example 5.3. Testing bad input to toRoman

class ToRomanBadInput(unittest.TestCase):
    def testTooLarge(self):
        """toRoman should fail with large input"""
        self.assertRaises(roman.OutOfRangeError, roman.toRoman, 4000) 1

    def testZero(self):
        """toRoman should fail with 0 input"""
        self.assertRaises(roman.OutOfRangeError, roman.toRoman, 0)    2

    def testNegative(self):
        """toRoman should fail with negative input"""
        self.assertRaises(roman.OutOfRangeError, roman.toRoman, -1)

    def testDecimal(self):
        """toRoman should fail with non-integer input"""
        self.assertRaises(roman.NotIntegerError, roman.toRoman, 0.5)  3
1 unittestTestCase �甦맑ュ assertRaises 回��況 靈×�ュ뎬, 그↔鋼 ヴ舡� 乾��槪 ��ヴ: �靴≠ 잇��� �ュ 잇�, �靴≠ �맑��淞ュ �ュ ��, 그靴� �靴≠ 그 ��읒 �弄�ュ 乾��. (梟� �靴≠ �맑��淞ュ 그 ��≠ �⌒ 健�� 乾�況 ≠��, 뮈밀�頌, 그� 匯듬況 assertRaises읒 �� ���, 그壽� 그↔鋼 그�槪 穢蟯尤 읓健�밀 �靴≠ �맑��� �ュ 그 ��읒 �弄 娛 ↔健ヴ.) �靴≠ 윈�읒밀 �� �ュ ↔읒 ��況 ��윈 숩�: toRoman槪 曳閻�劍頌 繇��� (그↔槪 try...except �刷읒 몃 �舡劍頌�) �虔꾑劍頌 그↔健 �샥� 잇�況 件劍�ュ� 瑩↑�ュ ��읒, assertRaisesュ 그 匯� ↔�槪 �靴 ��읒 �를優�ヴ. �靴≠ �ュ 匯� ↔鋼 그↔읒 잇�(roman.OutOfRangeError), ��(toRoman), 그靴� toRoman� 乾�(4000)�槪 �ュ ↔健ヴ, assertRaisesュ ���윈 toRoman槪 繇��� 그靴� 그↔健 roman.OutOfRangeError況 件劍�ュ� 蟯��∽ 瑩↑�ヴ. (�� 그靴� 잇�況 ���윈 �健�읒밀 匯� ↔鋼 ∥譴健ヴ�ュ ↔健 �譁寧 傑��� 蘆≠ �깜읒 꿇급� 件健 �ュ≠?)
2 樓朗 � 밝腱�槪 �맑���밀, �靴ュ 樓朗 虔鋼 밝腱�槪 �맑�� ��≠ �ヴ. ����, 頌梟 밝腱ュ 0 �ュ 舡� 穢�況 ��� � 꼬ヴ, 그甦밀 �靴ュ 그壽� 、、읒 �� �맑� �健맑況 ≠玲ヴ (testZero 그靴� testNegative). testZero읒밀, �靴ュ toRoman0劍頌 繇�� ┐ roman.OutOfRangeError 잇�況 件劍�ュ� �맑��ヴ; 梟� 그↔健 roman.OutOfRangeError況 件劍�� 꿩ュヴ� (그↔健 �靈� 』槪 �橒��寧 玗鋼, 그↔健 �┱ ヴ患 잇�況 件劍�� ┐珞읒), 健 �맑�ュ ��頌 。�들ヴ.
3 �깬獵� #3toRoman健 �-穢� 뱉�況 良껍�件 � 꼬ヴ� �穢�ヴ, 그甦밀 윈�읒밀 �靴ュ toRoman健 뱉�(0.5)頌 繇�� ┐ roman.NotIntegerError 잇�況 件劍�ュ� 蟯乾�ュ �맑�況 �ヴ. 梟� toRomanroman.NotIntegerError況 件劍�� 꿩ュヴ�, 健 �맑�ュ ��頌 。�들ヴ.

ヴ舡� 듬 �깬獵��鋼, toRoman��읒 fromRoman읒 ��들ヴュ 瑩梟 홉�ュ, 庚舡 뭐 ⌒잴 �며�ヴ:

  1. fromRomanュ 傑湧� 頌譁 밝腱況 ��꺌梟 �� 그靴� 그↔健 ���ュ 밝腱況 �橒�꺌 �ヴ.
  2. fromRoman鋼 朗湧� 頌譁 밝腱≠ ���� ���꺌 �ヴ.

�깬獵� #4ュ requirement #1�  鋼 籃�劍頌 庚靴��, 꿱淞玲 』�� ��槪 �손�윈밀 뮈밀�頌 、、槪 �맑��ヴ. �깬獵� #5ュ �깬獵� #2, #3�  鋼 籃�劍頌 庚靴��, 件蘇� 寧흴 建悚槪 �맑��� fromRoman健 그 �據� 잇�況 件劍�ュ� 蟯乾�ヴ.

Example 5.4. Testing bad input to fromRoman

class FromRomanBadInput(unittest.TestCase):
    def testTooManyRepeatedNumerals(self):
        """fromRoman should fail with too many repeated numerals"""
        for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):
            self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s) 1

    def testRepeatedPairs(self):
        """fromRoman should fail with repeated pairs of numerals"""
        for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
            self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)

    def testMalformedAntecedent(self):
        """fromRoman should fail with malformed antecedents"""
        for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
                  'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
            self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, s)
1 健↔읒 ��윈 ��ュ ↔鋼 그峀∽ �灑� 꿩ヴ; 健 ��鋼 �靴≠ toRoman읒 寧흴 建悚槪 �맑��ュ뎬 ���タ ��� 穢蟯�∽ �  ヴ. 兩∽ 恍� �靴ュ � ヴ患 잇�況 ≠玲ヴ� 寧ュ 恍� ↔健ヴ: roman.InvalidRomanNumeralError. 그↔鋼 (roman.OutOfRangeError 그靴� roman.NotIntegerError잴 �幢) roman.py꿴읒 穢�� ��≠ �ュ � 뭐 ⌒� 會� 잇�況 梟�ヴ. �靴ュ 健壽� 會� 잇�≠ 穢��ュ 輛槪, 健 �� ��쇰읒밀 숩∽ � ↔健ヴ. 그 ┐ �靴ュ �靈頌 roman.py況 꾄� 맸虔� ↔健ヴ.

5.5. 京�槪 胛� �맑�

腱�, 윈壽솥鋼 � �胛� ��≠, 숩� 순橒���� ��읒밀, �繇繇��乾 ���� 裔�槪 ���� �ュ ↔槪 烙¨� ↔健ヴ, ��읒밀 �寧ュ A況 B頌 순橒�� ヴ患 �寧ュ B況 A頌 순橒�ヴ. 健壽� ±��읒밀, 傑�� ↔鋼 “京� 瑩↑(sanity check)”況 虔뭡�윈 윈壽솥健 A 읒밀 B 頌 그靴� 을劍頌 A頌, 뱉�� 穢粱도況 楗��靴� 꿩�, �煌 읒壽況 件劍�� 꿩�, 玗鋼 ヴ患 �┱ 暎�� �그도 經烙맸�� 꿩�, 순橒� � �ヴュ ↔槪 蟯乾�ュ ↔健ヴ.

健塑 �깬獵�槪 휸、� 숩�

  1. 윈壽솥健 �寧� 밝腱況 ��밀, 그↔槪 頌譁 밝腱頌 순橒�ヴ�, 그靴�밀 ヴ맸 그↔槪 밝腱頌 순橒�ヴ�, 윈壽솥鋼 윈壽솥健 맸虔�タ 그 밝腱頌 ��≠ ��꺌 �ヴ. 그甦밀 1..3999읒 �ュ 匯�n읒 ��윈 'fromRoman(toRoman(n)) == n '健ヴ.

Example 5.5. Testing toRoman against fromRoman

class SanityCheck(unittest.TestCase):
    def testSanity(self):
        """fromRoman(toRoman(n))==n for all n"""
        for integer in range(1, 4000):        1 2
            numeral = roman.toRoman(integer)
            result = roman.fromRoman(numeral)
            self.assertEqual(integer, result) 3
1 �靴ュ �읒 range �� 況 셜 件健 �ヴ, 그壽寧 윈�읒밀 그↔鋼 듬 ⌒� 乾�頌 繇�들ヴ, 그↔鋼 穢��� 靴맑�況 �橒�ュ뎬 憬 纜櫻 乾� (1)읒밀 맸虔�윈 읓뱃�劍頌 듬 纜櫻 乾�(4000)�� 그壽寧 ���� 꿩�밀 묾ヴ. 그靴�윈, 1..3999, 그↔鋼 頌譁 밝腱頌 순橒�� 胛� 傑湧� �胛健ヴ.
2 蘆≠ �� 꿇급��腱 �ュ ↔鋼 (乾�) ����읒밀 integer(穢�)ュ �健�읒밀 ���≠ 껍レ�ュ ↔健ヴ; 윈�읒밀 그↔鋼 �� ヴ患 �┱ ↔� 譁�≠�頌 순�健華件 흣健ヴ.
3 윈�읒밀 �靈�乾 �맑� �靴ュ 曳밈�劍頌 꿱� 릴ヴ: �寧� 밝腱(integer)況 ��밀, 그↔槪 頌譁 밝腱(numeral)頌 순橒�ヴ, 그靴�묽 ヴ맸 그↔槪 밝腱(result)頌 순橒�� 그靴� 윈壽솥健 庚舡읒 맸虔�タ 그  鋼 밝腱頌 怒撚ュ�況 蟯乾�ヴ. 그峀� 꿩ヴ�, assertEqualュ 잇�況 件劍�� 그 �맑�ュ �맸 ��頌 。�� ↔健ヴ. 梟� 그 匯� 밝腱≠ 件���, assertEqualュ �� 獵�尤 둥껍이 ↔健�, 그 �譴 testSanity 回��ュ �균 獵��∽ 둥껍이 ↔健ヴ, 그靴� 그 �맑�ュ ��들 ↔劍頌 。� � ↔健ヴ.

譁�恢 듬 ⌒� �깬獵�鋼 ヴ患 ↔��ュ ヴ患뎬 ���� 그↔�鋼 � ヴ 巾��健� �뱉�� ┐珞健ヴ:

  1. toRomanュ �� �珞腱況 ���윈 頌譁 밝腱況 �橒�꺌 �ヴ, 그靴� fromRomanュ 읫曳 �珞腱� 頌譁 밝腱梟槪 良껍 �윈꺌 �ヴ (�, ヴ맸 恍�� 그↔鋼 뱉珞腱 建悚健 ���� ���꺌 �ヴ).
  2. fromRoman鋼 읫曳 �珞腱� 頌譁 밝腱梟槪 良껍 �윈꺌 �ヴ (�, ヴ맸 恍�� 그↔鋼 뱉珞腱 建悚健 ���� ���꺌 �ヴ).

��鋼, 그↔�鋼 �。鋼 巾��健ヴ. 잇況 ��, �靴ュ fromRoman 鋼 뱉珞腱잴 �뱉珞腱≠ 번乾 建悚槪 良껍�乾ヴ� ≠穢�ヴ. 그壽寧 그↔�鋼 잽�尤 巾��乾 ↔鋼 껍レヴ; 梟� toRoman健 �� �珞腱� �悚槪 �橒�ヴ�, 그壽� fromRoman鋼 ��도 �珞腱� 建悚槪 良껍�윈꺌梟 �ヴ, 그峀� 꿩劍� �靴� “京� 瑩↑(sanity check)” (�깬獵� #6)鋼 ��� ↔健ヴ. '그↔鋼 읫曳(only) �珞腱� 建悚梟槪 良껍 �乾ヴ'�� �ュ ��鋼 巾��健ヴ, 그壽寧 匯� 맸맑� ��耘頌≠ 윈壽솥읒∽ ±���健, �뱉珞腱ュ �� 珞靈�靴健ヴ, 그甦밀 그 �胛況 ��읒 �穢� ≠�≠ �ヴ. 그靴� 그↔健 �穢� 梟� ≠�≠ �ヴ�, �맑�� ≠�도 �ヴ

Example 5.6. Testing for case

class CaseCheck(unittest.TestCase):
    def testToRomanCase(self):
        """toRoman should always return uppercase"""
        for integer in range(1, 4000):
            numeral = roman.toRoman(integer)
            self.assertEqual(numeral, numeral.upper()) 1

    def testFromRomanCase(self):
        """fromRoman should only accept uppercase input"""
        for integer in range(1, 4000):
            numeral = roman.toRoman(integer)
            roman.fromRoman(numeral.upper())           2 3
            self.assertRaises(roman.InvalidRomanNumeralError,
                              roman.fromRoman, numeral.lower())
1 健 �맑� �健맑읒 ��윈 ≠� �藜頌� ↔鋼 그↔健 �맑��� 꿩ュ 匯� ↔健ヴ. 그↔鋼 toRoman劍頌쇰� �橒들 그 』健 �鋼� 玗鋼 ��� 件�뭡健 �ュ� �맑��� 꿩ュヴ; 그壽� �珞�鋼 샥⌒� �맑� �健맑읒 ��윈 ��윈 玲ヴ. �靴ュ �� �珞腱-乾↔ 梟槪 �맑��ュ 장�� �맑� �健맑況 ≠玲ヴ. 윈壽솥鋼 健↔槪, 그 �譴 �胛� 』�槪 ���� toRoman槪 繇��劍頌�, 京� 瑩↑ (sanity check)� ���� 멸鋼 傑玗읒 �� �도 匯患ヴ.[11] 그壽寧 그↔鋼 �셜�乾 깍��槪 胛�� ↔健ヴ: 、 �맑� �健맑ュ 읫曳 �⌒� �珞읒梟 ��윈꺌 �ヴ. 윈壽솥健 健 �健맑 瑩↑槪 그 京� 瑩↑� ����, 그靴� 그 �맑� �健맑≠ ���ヴ� ��� 숩�. 윈壽솥鋼 � �鋼 솥묠槪 �밀 그 �맑� �健맑� �ニ 쇰솥健 그 珞靈≠ 朗�乾�況 �穢�ュ뎬 ���ュ� 읓깬�윈꺌 � ↔健ヴ. 梟� 윈壽솥健 傑� �맑�� ���槪 솥묠�윈 �� 그↔�健 朗�槪 ┥�ュ�況 읓깬�꺌 �ヴ�, 그↔鋼 윈壽솥健 �맑� �健맑況 剛鰥-뒵腱乾�ヴュ 蟯�� �맸健ヴ.
2 윈�읒밀 ��꺌� �며� 귑饒健 �ヴ: toRomanュ �� �珞腱況 �橒�ヴュ ↔槪 “�靴≠ 꿱� �舡읒도” 숄깬��, �靴ュ �맸�劍頌 그↔� �橒 』槪 윈�읒밀 �珞腱頌 순橒�윈 fromRoman健 �珞腱 建悚槪 良껍�健ュ ↔槪 �맑��ヴ. �乾≠? ���� 'toRoman健 �� �珞腱況 �橒�ヴュ ↔'鋼 덱潢�乾 �깬獵�健� ┐珞健ヴ. 梟� �靴≠ 잇況 ��, 그↔健 �� 뱉珞腱況 �橒�도刷 �깬獵�槪 순±��, testToRomanCase �맑� �健맑ュ 순±��꺌 � ↔健ヴ, 그壽寧 健 �맑� �健맑ュ 윈�尤 虔돛� ↔健ヴ. 健↔鋼 � ヴ患 �靴� �셜�乾 깍�健ヴ: 、 �맑� �健맑ュ ヴ患 匯� ↔�ュ 샥⌒頌 虔돛� � ��꺌梟 �ヴ. 匯� �맑� �健맑ュ �潢들 묘健ヴ.
3 �靴ュ fromRoman� �橒 』槪 �뒵읒도 ���� 꿩ュヴュ ↔槪 ����. �健�읒밀 健↔鋼 �閻� 깬珞健ヴ; 梟� � ��≠ 』槪 �橒�읒도 숄깬�� 껍朗도 ��槪 ��健� 꿩劍�, �健�鋼 �� 그 �橒 』槪 �禍ヴ. 健 ±�읒, 그↔健 �靴≠ 읏� 力健ヴ. 健 �맑� �健맑ュ 그 �橒 』읒 ��윈 껍朗↔도 �맑��� 꿩ュヴ; 그↔鋼 �� fromRoman健 껍朗塑 잇�꼬健 �珞腱 建悚槪 良껍�健ュ�況 �맑��ヴ.

5.6. roman.py, 靈 1 ��

健靈 �靴� 傑� �맑�ュ 잽뭡��劍�頌, �靴� �맑� �健맑≠ �맑���況 맸도�� �ュ 力頌 그 ��況 虔뭡�� 맸虔� 맸。健ヴ. �靴ュ ��샥頌 健峀∽ �淞� �ヴ, 그甦밀 �靴ュ 匯� 傑� �맑�≠ ���ュ ↔槪 섰 � �ヴ 그靴�ュ �靴≠ roman.py꿴� ×��槪 回導� \읒 ��밀 �寧꼭 �寧꼭 그↔�健 ���ュ ↔槪 섰 � �ヴ.

Example 5.7. roman1.py

윈壽솥健 껍曳 그峀∽ �� 꿩뀜ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ���ュ ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

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

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

def toRoman(n):
    """convert integer to Roman numeral"""
    pass                                         4

def fromRoman(s):
    """convert Roman numeral to integer"""
    pass
1 健↔健 力頌 윈壽솥健 腱�梟� 會� 잇�況 �健�읒밀 穢��ュ 籃輛健ヴ. 잇�ュ �甦맑健ヴ, 그靴� 윈壽솥鋼 梧��ュ 잇��槪 �쇰�甦맑優 �劍頌� 腱�梟� 잇�況 휸뭡�ヴ. 윈壽솥健 Exception槪 (���乾 ↔鋼 껍レ�梟) �쇰�甦맑優 ��況 ∠悚尤 ���ヴ, 그↔鋼 匯� 蘆� 잇��健 �뱃�ュ �셜 �甦맑健ヴ. 윈�읒밀 寧ュ (Exception劍頌쇰� �뱃들) RomanError況 穢��ュ뎬, 그↔鋼 �셜 �甦맑頌 虔��윈 ヴ患 寧� 匯� 會� 잇��健 ��장ヴ. 健↔鋼 맑�件� 珞靈健ヴ; 寧ュ Exception �甦맑頌쇰� 曳閻�劍頌 껍� 릴∽ 、 ⌒샥�乾 잇�況 �뱃良槪 � ��ヴ.
2 OutOfRangeErrorNotIntegerError 잇�ュ �균읒ュ toRoman읒 ��윈 ����葉, ToRomanBadInput읒 �穢들 �頌, ヴ�� ��� 朗湧� 建悚槪 ��이淞 �繇� ↔健ヴ.
3 InvalidRomanNumeralError 잇�ュ �균 fromRoman읒 �� ����葉밀, FromRomanBadInput읒 �穢들 �頌, 朗湧� 建悚槪 ��이淞 �繇� ↔健ヴ.
4 健 ��읒밀, �靴ュ �靴� �� 、、槪 胛� API況 虔뭡��況 읏�ヴ, 그壽寧 �靴ュ 껍曳 그↔�槪 ����況 읏��ュ 꿩ュヴ, 그甦밀 �靴ュ �健�� 잇�� pass況 ���윈 그↔�槪 巾맸頌 뭐�ヴ.

健靈 그 �穢�乾 뮈。 (�韶槪 ��뭐� 듬듬듬~): �靴ュ �균 �靴� 傑� �맑�況 健 巾맸�乾 虔鋼 匯�읒 ��윈 ���淞� �ヴ. 健 맸瑩읒밀, 匯� �맑� �健맑ュ ���꺌 �ヴ. ��, 梟� �┱ �맑��도 靈 1 ��況 ���ヴ�, �靴ュ romantest.py頌 둥껍≠꺌梟 �� 그靴� � �靴≠ 껍朗↔도-��꿩ュ ���槪 ≠�� ��� 穢도頌 그峀∽ 껨匯 꼬ュ �맑�況 虔뭡�ュ�況 ��≠�꺌 �ヴ.

romantest1.py-v ���-�乾 묽���劍頌 ����, 그↔鋼 �� 腱뭐� �悚槪 숩윈 娛 ↔健� 그甦밀 �靴ュ 、 �맑� �健맑≠ ���ュ 돛꿴 穢蟯�∽ 朗�健 玲��� �ュ 섰 � �ヴ. �健 霓ヴ�, 윈壽솥� �悚鋼 健↔� �며�꺌梟 �ヴ:

Example 5.8. Output of romantest1.py against roman1.py

fromRoman should only accept uppercase input ... ERROR
toRoman should always return uppercase ... ERROR
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 ... FAIL
toRoman should give known result with known input ... FAIL
fromRoman(toRoman(n))==n for all n ... FAIL
toRoman should fail with non-integer input ... FAIL
toRoman should fail with negative input ... FAIL
toRoman should fail with large input ... FAIL
toRoman should fail with 0 input ... FAIL

======================================================================
ERROR: fromRoman should only accept uppercase input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 154, in testFromRomanCase
    roman1.fromRoman(numeral.upper())
AttributeError: 'None' object has no attribute 'upper'
======================================================================
ERROR: toRoman should always return uppercase
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 148, in testToRomanCase
    self.assertEqual(numeral, numeral.upper())
AttributeError: 'None' object has no attribute 'upper'
======================================================================
FAIL: fromRoman should fail with malformed antecedents
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 133, in testMalformedAntecedent
    self.assertRaises(roman1.InvalidRomanNumeralError, roman1.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\stage1\romantest1.py", line 127, in testRepeatedPairs
    self.assertRaises(roman1.InvalidRomanNumeralError, roman1.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\stage1\romantest1.py", line 122, in testTooManyRepeatedNumerals
    self.assertRaises(roman1.InvalidRomanNumeralError, roman1.fromRoman, s)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: InvalidRomanNumeralError
======================================================================
FAIL: fromRoman should give known result with known input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 99, in testFromRomanKnownValues
    self.assertEqual(integer, result)
  File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
    raise self.failureException, (msg or '%s != %s' % (first, second))
AssertionError: 1 != None
======================================================================
FAIL: toRoman should give known result with known input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 93, in testToRomanKnownValues
    self.assertEqual(numeral, result)
  File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
    raise self.failureException, (msg or '%s != %s' % (first, second))
AssertionError: I != None
======================================================================
FAIL: fromRoman(toRoman(n))==n for all n
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 141, in testSanity
    self.assertEqual(integer, result)
  File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
    raise self.failureException, (msg or '%s != %s' % (first, second))
AssertionError: 1 != None
======================================================================
FAIL: toRoman should fail with non-integer input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 116, in testDecimal
    self.assertRaises(roman1.NotIntegerError, roman1.toRoman, 0.5)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: NotIntegerError
======================================================================
FAIL: toRoman should fail with negative input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 112, in testNegative
    self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, -1)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: OutOfRangeError
======================================================================
FAIL: toRoman should fail with large input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 104, in testTooLarge
    self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, 4000)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: OutOfRangeError
======================================================================
FAIL: toRoman should fail with 0 input                                 1
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage1\romantest1.py", line 108, in testZero
    self.assertRaises(roman1.OutOfRangeError, roman1.toRoman, 0)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: OutOfRangeError                                        2
----------------------------------------------------------------------
Ran 12 tests in 0.040s                                                 3

FAILED (failures=10, errors=2)                                         4
1 그 맑�潢�況 ���� unittest.main()槪 ���ヴ, 그↔鋼 、 �맑� �健맑況 ���ヴ, 그↔鋼 romantest.py꿴� 、 �甦맑 꿴읒 穢�들 、 回��況 恍�ヴ. 、 �맑� �健맑읒 ��윈, 그↔鋼 그 回��� doc string� 그靴� �맑�≠ ���ュ� ���ュ�況 �悚�ヴ. 잇�� 力잴  健, �靴� �맑� �健맑 �ニ ↔도 ���� 鰥�ヴ.
2 ��� 、 �맑� �健맑읒 ��윈, unittest ュ 穢蟯�∽ 朗많 件健 件�撚ュ�況 숩윈�ュ 偈� 穢숩況 �悚�ヴ. 健 ±�읒, assertRaises읒 �� �靴� 繇�鋼 (also called failUnlessRaises) AssertionError況 件劍�ヴ ���� 그↔鋼 toRomanOutOfRangeError槪 件劍��況 잇��� ��劍寧 件�寧� 꿩뀜� ┐珞健ヴ.
3 그 腱뭐� �悚 �읒, unittestュ �譁寧 皇鋼 �맑�≠ ����ュ� 그靴� �譁寧 皇鋼 맸。健 �誦ュ�읒 �� ��穢숩況 숩윈影ヴ.
4 �譴�劍頌, 그 傑� �맑�ュ ���ヴ ���� ��도 �寧� �맑� �健맑ュ ���� 꿩� ┐珞健ヴ. �맑� �健맑≠ ���� 꿩槪 ┐, unittest ュ ��잴 읒壽 �健況 깬샥�ヴ. ��ュ assertEqual �ュ assertRaises잴  鋼, assertXYZ 回��읒 �� 繇�頌밀, 묽꿇들 獵�健 �健 껍レ�寧 玗鋼 그 잇�들 잇�≠ 烙휸�� 꿩뀜� ┐珞읒 ���ヴ. 읒壽ュ �靴≠ �맑��� �ュ �� 玗鋼 傑� �맑� �健맑 그 腱譴읒밀 件�寧ュ 匯� 暎�� 잇�健ヴ. 잇況 ��, testFromRomanCase 回��ュ (“fromRoman鋼 읫曳 �珞腱 建悚梟槪 閻��꺌梟 ��頌”) 읒壽윔ヴ, ���� numeral.upper()읒 �� 繇�健 AttributeError 잇�況 件劍�� ┐珞乾뎬, toRoman鋼 珞腱읽槪 �橒��頌 �� �劍寧 그峀� 꿩뀜� ┐珞健ヴ. 그壽寧 testZeroュ (“toRoman鋼 0 建悚劍頌ュ ���꺌 ��頌”) ��윔ヴ, ���� fromRoman읒 �� 繇�健 assertRaises≠ 黔� �ュ InvalidRomanNumeral 잇�況 件劍�� 꿩뀜� ┐珞健ヴ.

5.7. roman.py,靈 2 ��

健靈 �靴ュ roman 匯�� �屬巾��≠ 影� ��劍�頌, ��況 虔뭡�� �맑� �健맑況 ��娛 맸。健ヴ.

Example 5.9. roman2.py

윈壽솥健 껍曳 그峀∽ �� 鰥�윔ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

"""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), 1
                   ('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 toRoman(n):
    """convert integer to Roman numeral"""
    result = ""
    for numeral, integer in romanNumeralMap:
        while n >= integer:      2
            result += numeral
            n -= integer
    return result

def fromRoman(s):
    """convert Roman numeral to integer"""
    pass
1 romanNumeralMapュ ��� ��頌밀 뭐 ≠�況 穢��ヴ:
  1. ≠� �셜�乾 頌譁 밝腱� 珞腱 ���. ��� ↔鋼 健↔健 �� �⌒若靴-珞腱頌들 頌譁 밝腱≠ 껍レ�ュ ↔健ヴ; �靴ュ ��, CM�  鋼, 듬-珞腱頌 들 �槪 穢��ヴ (“1000숩ヴ 100虔鋼 �”); 健↔鋼 健�읒 �靴� toRoman ��況 �� �뮈�∽ 梟� ↔健ヴ.
  2. 頌譁 밝腱�� 뮈밀. 그↔�鋼, M劍頌쇰� 冶 I��, 蘆煌量뮈 』� 뮈밀頌 寧읽들ヴ.
  3. 、 頌譁 밝腱� 』. 蘆쇰� 、 ��鋼 (numeral, value)� �健ヴ.
2 윈�≠ 力頌 �靴� �쇰� 뎬健� 깬獵≠ 健鋸槪 蘆ュ ≒健ヴ, ���� �靴ュ 그 홉� 깍�槪 庚靴�� 胛�윈 �┱ �샥� �靴도 ���� 꿩� ┐珞健ヴ. 頌譁 밝腱頌 순橒�� 胛�밀, �靴ュ �뮈�∽ romanNumeralMap槪 �손�윈 �靴� 建悚숩ヴ 虔�寧  鋼 ≠� � 穢� 』槪 黔�梟 �� 들ヴ. 烙¨��, �靴ュ 그 頌譁 밝腱 ��槪 그 �悚� 譁�恢읒 偈≠��, 그 建悚劍頌쇰� 그 �皆�ュ 穢�況 훌ヴ, 그靴� ヴ맸 �손�ヴ.

Example 5.10. How toRoman works

梟� 윈壽솥健 �┍∽ toRoman健 虔돛�ュ� 剛 匯花∫ヴ�, print 밀�珞槪 while 耘둥健� 譁�恢읒 偈≠��:

        while n >= integer:
            result += numeral
            n -= integer
            print 'subtracting', integer, 'from input, adding', numeral, 'to output'
>>> import roman2
>>> roman2.toRoman(1424)
subtracting 1000 from input, adding M to output
subtracting 400 from input, adding CD to output
subtracting 10 from input, adding X to output
subtracting 10 from input, adding X to output
subtracting 4 from input, adding IV to output
'MCDXXIV'

그甦밀 toRomanュ ��도 �靴� 巾맸 �돛 瑩↑읒밀ュ, 虔돛�ュ �健 숩乾ヴ. 그壽寧 그↔健 傑� �맑�況 ����? 舡 껍レヴ, ��劍頌ュ 껍レヴ.

Example 5.11. Output of romantest2.py against roman2.py

fromRoman should only accept uppercase input ... FAIL
toRoman should always return uppercase ... ok                  1
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 ... FAIL
toRoman should give known result with known input ... ok       2
fromRoman(toRoman(n))==n for all n ... FAIL
toRoman should fail with non-integer input ... FAIL            3
toRoman should fail with negative input ... FAIL
toRoman should fail with large input ... FAIL
toRoman should fail with 0 input ... FAIL
1 toRoman鋼, ��, �� �珞腱況 �橒�ヴ, ���� �靴� romanNumeralMap健 頌譁 밝腱 ���槪 �珞腱頌 穢��� ┐珞健ヴ. 그甦밀 健 �맑�ュ 健藜 ��� �寧 ヴ華꼬ヴ.
2 윈�읒 �京祿 ゼ맑≠ �ヴ: toRoman ��� 健 ��鋼 꿱淞玲 』 �맑�況 ���ヴ. ����, 그↔鋼 �□�健�ュ 꿩ヴ, 그壽寧 그↔鋼 ヴ�� 霓鋼 建悚槪 ≠��, 그 ��� �悚槪 �≠�ヴ. 그 建悚읒 ���ュ ↔鋼 �⌒若靴-珞腱� 匯� 頌譁 밝腱況 ���ュ 建悚�, ≠�� ≠� � 建悚 (3999), 그靴� ≠�� ≠� � 頌譁 밝腱 (3888)況 ���ュ 建悚健ヴ. 健 맸瑩읒밀, �靴ュ 그 ��≠ �靴≠ タ葉 �槪 � �ュ �─� 霓鋼 建悚』읒도 虔돛�ヴ� �靴�劍頌 蟯�� � �ヴ.
3 그峀�梟 그 ��ュ 寧흴 』읒 ��윈ュ“虔돛��” 꿩ュヴ; 그↔鋼 匯� ⌒샥� 寧흴 建悚 �맑�읒 ���ヴ. 그↔鋼 �읓�ヴ, ���� �靴≠ 寧흴 建悚읒 ��윈 �┱ 瑩↑쇰도 ���� 꿩뀜� ┐珞健ヴ. 그壽� �맑� �健맑ュ (assertRaises況 ��윈) �穢� 잇�≠ 件�寧�況 �ヴ禍ヴ, 그靴� �靴ュ 그↔�槪 烙휸맸�� 꿩ュヴ. �靴ュ ヴ舡 ��읒밀 그峀∽ � ↔健ヴ.

윈�읒 그 傑� �맑�� �悚��≠ ��밀, 그 匯� ���읒 �� 뭐쇰��槪 寧읽�ヴ. �靴ュ 10⌒� 읒壽況 會健�ヴ.


======================================================================
FAIL: fromRoman should only accept uppercase input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage2\romantest2.py", line 156, in testFromRomanCase
    roman2.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\stage2\romantest2.py", line 133, in testMalformedAntecedent
    self.assertRaises(roman2.InvalidRomanNumeralError, roman2.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\stage2\romantest2.py", line 127, in testRepeatedPairs
    self.assertRaises(roman2.InvalidRomanNumeralError, roman2.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\stage2\romantest2.py", line 122, in testTooManyRepeatedNumerals
    self.assertRaises(roman2.InvalidRomanNumeralError, roman2.fromRoman, s)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: InvalidRomanNumeralError
======================================================================
FAIL: fromRoman should give known result with known input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage2\romantest2.py", line 99, in testFromRomanKnownValues
    self.assertEqual(integer, result)
  File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
    raise self.failureException, (msg or '%s != %s' % (first, second))
AssertionError: 1 != None
======================================================================
FAIL: fromRoman(toRoman(n))==n for all n
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage2\romantest2.py", line 141, in testSanity
    self.assertEqual(integer, result)
  File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
    raise self.failureException, (msg or '%s != %s' % (first, second))
AssertionError: 1 != None
======================================================================
FAIL: toRoman should fail with non-integer input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage2\romantest2.py", line 116, in testDecimal
    self.assertRaises(roman2.NotIntegerError, roman2.toRoman, 0.5)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: NotIntegerError
======================================================================
FAIL: toRoman should fail with negative input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage2\romantest2.py", line 112, in testNegative
    self.assertRaises(roman2.OutOfRangeError, roman2.toRoman, -1)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: OutOfRangeError
======================================================================
FAIL: toRoman should fail with large input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage2\romantest2.py", line 104, in testTooLarge
    self.assertRaises(roman2.OutOfRangeError, roman2.toRoman, 4000)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: OutOfRangeError
======================================================================
FAIL: toRoman should fail with 0 input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage2\romantest2.py", line 108, in testZero
    self.assertRaises(roman2.OutOfRangeError, roman2.toRoman, 0)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: OutOfRangeError
----------------------------------------------------------------------
Ran 12 tests in 0.320s

FAILED (failures=10)

5.8. roman.py, 靈 3 ��

健靈 toRoman健 (1읒밀 3999��� 穢��) 霓鋼 建悚劍頌ュ 穢蟯�∽ �돛��頌, 그↔槪 (ヴ患 匯� ↔乾) 寧흴 建悚』劍頌도 穢蟯�∽ �돛�도刷 梟� 맸。健ヴ.

Example 5.12. roman3.py

윈壽솥健 껍曳 그峀∽ �� 鰥�윔ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

"""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))

def toRoman(n):
    """convert integer to Roman numeral"""
    if not (0 < n < 4000):                                             1
        raise OutOfRangeError, "number out of range (must be 1..3999)" 2
    if int(n) <> n:                                                    3
        raise NotIntegerError, "decimals can not be converted"

    result = ""                                                        4
    for numeral, integer in romanNumeralMap:
        while n >= integer:
            result += numeral
            n -= integer
    return result

def fromRoman(s):
    """convert Roman numeral to integer"""
    pass
1 健↔鋼 獲�ュ �健�ヴ� �華굶健ヴ: �纜읒 ヴ燁 �귑. 健↔鋼 'if not ((0 < n) and (n < 4000))'� 돛��ヴ, 그壽寧 그↔健 雨꽉 � 居�읒 릴ヴ. 健↔鋼 �靴� �胛 瑩↑健ヴ, 그靴� 그↔鋼 樓朗 � 』, 舡�, �ュ 0乾 建悚』槪 寧��꺌梟 �ヴ.
2 윈壽솥鋼 맑맑頌 raise 밀�珞槪 ≠�� 잇�況 件劍�ヴ. 윈壽솥鋼 �─� 蘆� 잇�도 件劍� � �劍� �ュ 윈壽솥健 穢�� �─� 會� 잇�도 件劍� � �ヴ. 듬 纜櫻 �⌒순�, 그 읒壽 回맸�ュ, 묽��健ヴ; 梟� ��玲ヴ�, 그 잇�≠ 庚靴�� 꿩槪 ±�읒 �悚�ュ 을 偈� 回맸�읒 그↔鋼 �悚� ↔健ヴ.
3 健↔鋼 �靴� 뱉� 瑩↑健ヴ. 뱉�ュ 頌譁밝腱頌 순橒� � 꼬ヴ.
4 健 ��� 寧蛔�ュ 순±�� 꿩ュヴ.

Example 5.13. Watching toRoman handle bad input

>>> import roman3
>>> roman3.toRoman(4000)
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
  File "roman3.py", line 27, in toRoman
    raise OutOfRangeError, "number out of range (must be 1..3999)"
OutOfRangeError: number out of range (must be 1..3999)
>>> roman3.toRoman(1.5)
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
  File "roman3.py", line 29, in toRoman
    raise NotIntegerError, "decimals can not be converted"
NotIntegerError: decimals can not be converted

Example 5.14. Output of romantest3.py against roman3.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 ... FAIL
toRoman should give known result with known input ... ok 1
fromRoman(toRoman(n))==n for all n ... FAIL
toRoman should fail with non-integer input ... ok        2
toRoman should fail with negative input ... ok           3
toRoman should fail with large input ... ok
toRoman should fail with 0 input ... ok
1 toRoman鋼 윈�尤 꿱淞玲 』 �맑�況 ���ュ뎬, 그↔鋼 ��� 件健ヴ. 靈 2 ��읒밀 ��들 匯� �맑�도 윈�尤 ���ヴ, 그甦밀 �靴� 譁�恢 ��ュ 껍朗↔도 淮≠�靴� 꿩뀜ヴ.
2 �� �寧ュ 件鋼 �靴� 匯� 寧흴 建悚 �맑�≠ 健靈 ���ヴュ ↔健ヴ. 健 �맑�, testDecimalint(n) <> n� 瑩↑쇰 ┐珞읒 ���ヴ. 뱉�≠ toRoman읒 ��� ┐, int(n) <> n 瑩↑쇰ュ 그↔槪 꿱껍梗� NotIntegerError 잇�況 件劍�ュ뎬, 그↔健 力頌 testDecimal健 �ヴ靴� �ュ ↔健ヴ.
3 健 �맑�, testNegativenot (0 < n < 4000) 瑩↑쇰 ┐珞읒 ���ヴ, 그↔鋼 OutOfRangeError 잇�況 件劍�ュ뎬, 그↔健 力頌 testNegative≠ �ヴ靴� �ュ ↔健ヴ.

======================================================================
FAIL: fromRoman should only accept uppercase input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage3\romantest3.py", line 156, in testFromRomanCase
    roman3.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\stage3\romantest3.py", line 133, in testMalformedAntecedent
    self.assertRaises(roman3.InvalidRomanNumeralError, roman3.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\stage3\romantest3.py", line 127, in testRepeatedPairs
    self.assertRaises(roman3.InvalidRomanNumeralError, roman3.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\stage3\romantest3.py", line 122, in testTooManyRepeatedNumerals
    self.assertRaises(roman3.InvalidRomanNumeralError, roman3.fromRoman, s)
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: InvalidRomanNumeralError
======================================================================
FAIL: fromRoman should give known result with known input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage3\romantest3.py", line 99, in testFromRomanKnownValues
    self.assertEqual(integer, result)
  File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
    raise self.failureException, (msg or '%s != %s' % (first, second))
AssertionError: 1 != None
======================================================================
FAIL: fromRoman(toRoman(n))==n for all n
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage3\romantest3.py", line 141, in testSanity
    self.assertEqual(integer, result)
  File "c:\python21\lib\unittest.py", line 273, in failUnlessEqual
    raise self.failureException, (msg or '%s != %s' % (first, second))
AssertionError: 1 != None
----------------------------------------------------------------------
Ran 12 tests in 0.401s

FAILED (failures=6) 1
1 �靴ュ 6 ⌒� 읒壽況 會健�ヴ, 그靴� 그� 匯듬ュ fromRoman읒 읓�들ヴ: 꿱淞玲 』 �맑�, 뭐⌒� ⌒샥�乾 寧흴 建悚 �맑�, �뱉珞腱 瑩↑, 그靴� 京� 瑩↑. 그↔鋼 toRoman健 맑맑頌 ��� � �ュ 匯� �맑�況 ���윔ヴュ ↔槪 �藜�ヴ. (그↔鋼 京� 瑩↑� 읓�들ヴ, 그壽寧 그↔鋼 �� fromRoman健 虔뭡��況 �깬�ヴ, 그↔鋼 껍曳 虔뭡�� 꿩뀜ヴ.) 그↔鋼 �靴≠ �� toRoman槪 ����況 丸偈�꺌 �ヴュ ↔槪 �藜�ヴ. �─� ���도, �─� 獵虔도, “梟件읒 ���” �─� 偈≠�乾 瑩↑도 匯듬ヴ ����. 燁���. ��. �숩�頌쇰� �靴 ┮�葉�.
Note
�□�乾 傑� �맑�≠ 윈壽솥읒∽ 꿱淞娛 � �ュ ≠� 燁�� ↔鋼 꿇靈 ��槪 丸偈ュ≠健ヴ. � ��況 胛� 匯� 傑� �맑�≠ ��� ┐, 그 ��況 ���ュ ↔槪 燁���. �譴 匯�읒 �� 匯� 傑� �맑�≠ ��� ┐, 그 匯�槪 ���ュ ↔槪 燁���.

5.9. roman.py, 靈 4 ��

健靈 toRoman健 잽뭡��劍�頌, fromRoman槪 ��� 맸。健ヴ. ⌒샥�乾 頌譁 밝腱況 穢� 』劍頌 羊�� �ュ �靴� �쇰� 뎬健� 깬獵 �솥읒, 健↔鋼 toRoman ��잴 譁�≠�頌 �貰� 꿩ヴ.

Example 5.15. roman4.py

윈壽솥健 껍曳 그峀∽ �� 鰥�ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

"""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: 1
            result += integer
            index += len(numeral)
    return result
1 윈�읒밀� ��鋼 toRoman� 돛件�ヴ. �靴ュ 頌譁 밝腱 뎬健� 깬獵(���� ��)況 耘둥健 �ヴ, 그靴� ≠��� ≠� �鋼 穢� 』읒 羊��ュ ��읒, �靴ュ ≠��� “≠� �鋼” 頌譁 밝腱 珞腱읽읒 羊��ヴ.

Example 5.16. How fromRoman works

윈壽솥健 �┍∽ fromRoman健 虔돛�ュ� 健��� 鰥�∫ヴ�, print 밀�珞槪 while 耘둥健� 딘읒ヴ≠ 偈≠��:

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

Example 5.17. Output of romantest4.py against 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 1
toRoman should give known result with known input ... ok
fromRoman(toRoman(n))==n for all n ... ok                  2
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
1 윈�읒 듬 ⌒� �寧ュ 뱉�健 �ヴ. 憬 櫻ュ fromRoman健 霓鋼 建悚읒, ��도 �靴≠ �맑��ュ 그 꿱淞玲 』�읒 ��윈, 虔돛�ヴュ ↔健ヴ.
2 � 櫻ュ �靴� 京� 瑩↑(sanity check) 을맸 ���ヴュ ↔健ヴ. 그 꿱淞玲 』 �맑�잴 ���숩�, �靴ュ 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)

5.10. roman.py, 靈 5 ��

健靈 fromRoman健 霓鋼 建悚劍頌ュ �據�∽ 虔돛��頌, 그 ��� 譁�恢 獵、槪 會偈� ��꺌 � 맸。健ヴ: 寧흴 建悚劍頌 그↔槪 �據尤 虔돛�도刷 �ュ ↔. 그↔鋼 珞腱읽槪 숩ュ 籃輛槪 黔ュ ↔槪 �藜�� 그靴� 그↔健 傑湧� 頌譁 밝腱乾�況 �穢�ュ 籃輛槪 黔ュ ↔槪 �藜�ヴ. 健↔鋼 toRoman읒밀 �� 建悚槪 �≠�ュ ↔숩ヴ 셜��劍頌 � �貰ヴ, 그壽寧 �靴읒∽ュ 譁舡�頌 ��� � �ュ ∠悚� 도깬≠ �ヴ: 穢깍 ���.

梟� 윈壽솥健 穢깍 ���읒 鋸밍�� 鰥�� 그靴� 穢깍 ��� 101槪 居� 꿩뀜ヴ�, ��健 力頌 霓鋼 �耘≠ � ↔健ヴ.

�靴≠ 健 �� 밀�읒 셜 力잴  健, 頌譁 밝腱 �寧況 깬뭡�ュ 뎬읒ュ �。� 。�� 깍�健 �ヴ. 憬 纜櫻ュ 絹�胛 腱靴ュ, 梟� �ヴ�, 件蘇� M 珞腱읒 ��밀 ��들ヴ.

Example 5.18. Checking for thousands

>>> import re
>>> pattern = '^M?M?M?$'       1
>>> re.search(pattern, 'M')    2
<SRE_Match object at 0106FB58>
>>> re.search(pattern, 'MM')   3
<SRE_Match object at 0106C290>
>>> re.search(pattern, 'MMM')  4
<SRE_Match object at 0106AA38>
>>> re.search(pattern, 'MMMM') 5
>>> re.search(pattern, '')     6
<SRE_Match object at 0106F4A8>
1 健 ��鋼 뭐 ⌒� 쇰솥槪 ≠玲ヴ:
  1. ^ - 그 珞腱읽� � 꽜읒밀 ��읫ュ ↔읒 件��ヴ. 梟� 健↔健 �穢�� 꿩劍�, 그 ��鋼 M 珞腱≠ �뒵읒 ��� 。읒 件�� ↔健ヴ, 그↔鋼 �靴≠ 읏�ュ ↔健 껍レヴ. �靴ュ M 珞腱≠, 梧���梟 �ヴ�, 그 珞腱읽� � 꽜읒 �ヴュ ↔槪 蟯乾��況 읏�ヴ.
  2. M? - 묽��劍頌 �⌒� M 珞腱읒 件��ヴ. 健↔健 뭐 纜 �손��頌, �靴ュ � 娛읒 0읒밀 3⌒��� M 珞腱≠ �ュ ≒健� �ニ ≒健寧 件�맸�ヴ.
  3. $ - 그 珞腱읽� � 딘읒밀 꽜밀 �ュ ↔읒 件��ヴ. � 꽜� ^ 珞腱잴 ����, 健↔鋼 그 ��健 그 �譴 珞腱읽읒, M 珞腱� 꽜健寧 딘읒 껍朗塑 珞腱꼬健, 件��꺌 �ヴュ ↔槪 ┥�ヴ.
2 re 匯�� ��鋼 search ��健ヴ, 그↔鋼 穢깍 ���(pattern)� 그靴� 珞腱읽('M')槪 ��밀 그 穢깍 ���� 羊�� 숩淞� 맸도�ヴ. 梟� 件�≠ 烙¨��, searchュ �寧� ∥譴況 �橒�ヴ; 그 ∥譴ュ 그 件�況 腱뭐尤 ��� �ュ ヴ�� 回��況 ≠玲ヴ; 梟� 件�≠ 烙¨�� 꿩劍�, searchュ �健�� 朗湧 』乾, None槪 �橒�ヴ. (�刷 그↔健 �藜��ュ ��梟), �靴ュ search≠ �橒�ュ 그 ∥譴읒 ��윈 뭐쇰�劍頌 ��≠�ュ 꿩∫ヴ. ���� 健 뮈。읒 �靴≠ ��槪 ≠�ュ 匯� ↔鋼 그 ��健 件��ュ≠� 윈쇰健� ┐珞健ヴ, 그↔槪 �靴ュ �� search� 그 �橒』槪 ��섯劍頌� 恍� � �ヴ. 'M'ュ 健 穢깍 ���읒 件��ヴ, ���� 그 憬 纜櫻 묽��乾 M健 件��� 그靴� 그 듬纜櫻 그靴� 그 뭐纜櫻� 묽��乾 M 珞腱�鋼 朗맸�� ┐珞健ヴ.
3 'MM'ュ 件��ヴ ���� 그 憬纜櫻 그靴� 듬 纜櫻 묽��乾 M 珞腱≠ 件��� 그 뭐纜櫻 M鋼 朗맸�� ┐珞健ヴ.
4 'MMM'鋼 件��ヴ ���� 뭐 ⌒� 匯� M 珞腱≠ 件��� ┐珞健ヴ.
5 'MMMM'鋼 件��� 꿩ュヴ. 뭐 ⌒� 匯� M 珞腱ュ 件��ヴ, 그壽寧 그靴� 寧밀 그 穢깍 ���鋼 ($ 珞腱 ┐珞읒) 그 珞腱읽� 怒槪 ���ヴ, 그靴� 그 珞腱읽鋼 (弄纜櫻� M ┐珞읒) 껍曳 怒寧� 꿩ュヴ. 그甦밀 searchNone槪 �橒�ヴ.
6 �藜�∽도, � 珞腱읽 �� 健 穢깍 ���읒 件��ヴ, ���� 匯� M 珞腱�健 묽��健� ┐珞健ヴ. 健 ��槪 웩듬읒 듬��; 그↔鋼 ヴ舡 뭏�읒밀 �� 燁��∽ � ↔健ヴ.

�� 腱靴ュ 絹� 腱靴숩ヴ �� �貰ヴ, ����, 그 』읒 ��밀, �繇 ���劍頌 ��� � �ュ 윈壽 籃輛�健 �� ┐珞健ヴ.

그甦밀 弄 ⌒� ≠�� ��健 �ヴ:

  1. CM
  2. CD
  3. 0 읒밀 3⌒ ��� C 珞腱� (梟� �� 腱靴≠ 0健� 0⌒)
  4. D, ヴ舡읒 0읒밀 3⌒ ��� C 珞腱�健 �患ヴ

譁�恢 듬 ⌒� ��鋼 獵�� � �ヴ:

Example 5.19. Checking for hundreds

>>> import re
>>> pattern = '^M?M?M?(CM|CD|D?C?C?C?)$' 1
>>> re.search(pattern, 'MCM')            2
<SRE_Match object at 01070390>
>>> re.search(pattern, 'MD')             3
<SRE_Match object at 01073A50>
>>> re.search(pattern, 'MMMCCC')         4
<SRE_Match object at 010748A8>
>>> re.search(pattern, 'MCMC')           5
>>> re.search(pattern, '')               6
<SRE_Match object at 01071D98>
1 健 ��鋼, 그 珞腱읽� � 꽜槪 瑩↑�� (^), 그靴�ュ �� 腱靴 (M?M?M?)況 瑩↑�ュ 健�� �靴� ��� �  健 맸虔�ヴ. 그靴� �靴ュ, □繇꿴읒, �頌� 쇰솥槪 ≠玲ヴ, 그↔鋼 件�� 뭐⌒� �繇 ���乾 ��槪, �曳 恢�頌 솥靴�윈, 穢��ヴ: CM, CD, 그靴� D?C?C?C? (그↔鋼 묽��乾 D頌밀ヴ舡읒 0읒밀 3⌒��� 묽��乾 C 珞腱≠ �患ヴ). 그 穢깍 ��� �묠�(PARSER)ュ 健壽� ��� 、、槪 (잗臆읒밀 읫患臆劍頌) 뮈밀�頌 瑩↑�윈, 件��ュ 憬 纜櫻 ↔槪 ���, 그 寧蛔�ュ 朗맸�ヴ.
2 'MCM'鋼 件��ヴ ���� 憬 纜櫻 M健 件���, 듬纜櫻잴 뭐纜櫻 M 珞腱�鋼 朗맸�� ┐珞健ヴ, 그靴� CM鋼 件��ヴ (그甦밀 CDD?C?C?C? ��鋼 �淞獵量 �� 꿩ュヴ). MCM1900� 頌譁밝腱 ��健ヴ.
3 'MD'≠ 件��ヴ ���� 그 憬纜櫻 M健 件��� ┐珞健ヴ, 그 듬 纜櫻잴 뭐 纜櫻 M 珞腱�鋼 朗맸들ヴ, 그靴� D?C?C?C? ��鋼 D읒 件��ヴ (그 3⌒� C 珞腱�鋼 묽��健� 朗맸들ヴ). MD1500� 頌譁 밝腱 ��健ヴ. 'MD'≠ 件��ヴ ���� 그 憬纜櫻 M健 件���, 듬纜櫻잴 뭐纜櫻 M 珞腱ュ 朗맸�� ┐珞健ヴ, 그靴� D?C?C?C? ��鋼 D읒 件��ヴ (3⌒� C 珞腱� 、、鋼 묽��健�밀 朗맸들ヴ). MD1500� 頌譁 밝腱 ��健ヴ.
4 'MMMCCC'≠ 件��ヴ ���� 3⌒� M 珞腱 匯듬≠ 件��� ┐珞健ヴ, 그靴� D?C?C?C? ��鋼 CCC읒 件��ヴ (Dュ 묽��健� 朗맸들ヴ) MMMCCC3300� 頌譁 밝腱 ��健ヴ. 'MMMCCC'鋼 件��ヴ ���� 3⌒� 匯� M 珞腱�健 件��� ┐珞健ヴ, 그靴� D?C?C?C? ��鋼 CCC읒 件��ヴ ( Dュ 묽��健�밀 朗맸들ヴ). MMMCCC3300� 頌譁 밝腱 ��健ヴ.
5 'MCMC'ュ 件��� 꿩ュヴ. 憬 纜櫻 M鋼 件��ヴ, 듬纜櫻잴 뭐纜櫻 M 珞腱ュ 朗맸들ヴ, 그靴� CM鋼 件��ヴ, 그壽寧 'MCMC'ュ 件��� 꿩ュヴ. 憬纜櫻 M鋼 件��ヴ, 듬纜櫻잴 뭐纜櫻 M 珞腱�鋼 朗맸들ヴ, 그靴� CM鋼 件��ヴ, 그壽寧 그壽� $ュ 件��� 꿩ュ뎬 ���� �靴ュ 그 珞腱읽� 譁�恢읒 껍曳 도恙�� 꿩뀜� ┐珞健ヴ (�靴ュ 윈�尤 件��� 꿩鋼 C 珞腱況 ≠玲ヴ). CD?C?C?C? ��� 쇰솥劍頌 件��� 꿩ュヴ , ���� 그 �繇 �靈�乾 CM ��健 健藜 件��� ┐珞健ヴ.
6 �藜�∽도, � 珞腱읽鋼 윈�尤 健 ��읒 件��ヴ, ���� 匯� M 珞腱�鋼 묽��健� 朗맸�� ┐珞健ヴ, 그靴� 그 � 珞腱읽鋼 D?C?C?C? ��읒 件��ヴ ��읒밀ュ 匯� 珞腱�健 묽��健� 朗맸�� ┐珞健ヴ.

祐�! 穢깍 ���健 �譁寧 횰靴 ��껍�� � �ュ� 꿱∫ュ≠? 그靴� �靴ュ �� �� 腱靴잴 絹� 腱靴梟槪 ヴ��槪 흣健ヴ. (健 �� ��쇰읒밀, �靴ュ 穢깍 ���槪 虔뭡�ュ �。 ヴ患 깬珞槪 숩∽ � ↔健ヴ, �  健 손���ュ �∫�梟, ��도 그↔鋼 그 ���� ヴ患 쇰솥읒 �乾-꿴 珞밀優況 ���ヴ.) ヴ�맑笹∽도, 梟� 윈壽솥健 그 匯� ↔槪 ��。ヴ�, 멩� 腱靴잴 件� 腱靴ュ 릴ヴ, ���� 그↔�鋼 穢蟯尤  鋼 ��健� ┐珞健ヴ.

Example 5.20. roman5.py

윈壽솥健 껍曳 그峀∽ �� 꿩뀜ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

"""Convert to and from Roman numerals"""
import re

#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))

def toRoman(n):
    """convert integer to Roman numeral"""
    if not (0 < n < 4000):
        raise OutOfRangeError, "number out of range (must be 1..3999)"
    if int(n) <> n:
        raise NotIntegerError, "decimals can not be converted"

    result = ""
    for numeral, integer in romanNumeralMap:
        while n >= integer:
            result += numeral
            n -= integer
    return result

#Define pattern to detect valid Roman numerals
romanNumeralPattern = '^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$' 1

def fromRoman(s):
    """convert Roman numeral to integer"""
    if not re.search(romanNumeralPattern, s):                                    2
        raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s

    result = 0
    index = 0
    for numeral, integer in romanNumeralMap:
        while s[index:index+len(numeral)] == numeral:
            result += integer
            index += len(numeral)
    return result
1 健↔鋼 �� �靴≠ 셜, 絹� 腱靴잴 �� 腱靴況 庚靴�タ 그 ��� 읓뱃健ヴ. 멩� 腱靴ュ XC (90), XL (40)健�寧 , 玗鋼 묽��乾 L頌밀 ヴ舡읒 0⌒읒밀 3⌒��� 묽��乾 X 珞腱≠ �患ヴ. 件� 腱靴ュ IX (9), IV (4)健�寧, 玗鋼 묽��乾 V頌밀 ヴ舡읒 0⌒읒밀 3⌒��� 묽��乾 I 珞腱≠ �患ヴ.
2 그 匯� �靴況 �靴� 穢깍 ���읒 ��� ��劍�頌, 朗湧� 頌譁 밝腱況 瑩↑�ュ ��ュ �뱉� 件健 들ヴ. 梟� re.search≠ ∥譴況 �橒��, 그壽� 그 穢깍 ���鋼 件��� 그靴� �靴� 建悚鋼 傑湧�ヴ; 그峀� 꿩劍�, �靴� 建悚鋼 朗湧�ヴ.

健 맸瑩읒밀, 그 ��� 鰥휸� 穢깍 ���健 匯� 暎�� 朗湧� 頌譁 밝腱況 寧�� � �ヴュ ↔槪 윈壽솥鋼 ���도 霓ヴ. 그壽寧 蘆 恍槪 ◎健 ◎�頌 礪� 譁�, 그 ���槪 �� 숩�:

Example 5.21. Output of romantest5.py against roman5.py


fromRoman should only accept uppercase input ... ok          1
toRoman should always return uppercase ... ok
fromRoman should fail with malformed antecedents ... ok      2
fromRoman should fail with repeated pairs of numerals ... ok 3
fromRoman should fail with too many repeated numerals ... ok
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

----------------------------------------------------------------------
Ran 12 tests in 2.864s

OK                                                           4
1 穢깍 ���읒 ��윈 蘆≠ 꿇급�� 꿩鋼 � ≠�ュ, �셜�劍頌, 穢깍 ���鋼 �뱉珞腱-濾\ �ヴュ ↔健ヴ. �靴� 穢깍 ��� romanNumeralPattern健 �珞腱頌 ����劍�頌, �靴� re.search 瑩↑鋼 잽��∽ �珞腱≠ 껍� �┱ 建悚도 �쇰� ↔健ヴ. 그甦밀 �靴� �珞腱 建悚 �맑�ュ ���ヴ.
2 �� 燁��∽도, �靴� 寧흴 建悚 �맑�ュ ���ヴ. 잇況 ��, 그 鰥휸� 獵� �맑� �健맑ュ MCMC잴  鋼 �健맑況 瑩↑�ヴ. 윈壽솥健 셜 力잴  健, 健↔鋼 �靴� 穢깍 ���읒 件��� 꿩ュヴ, 그甦밀 fromRomanInvalidRomanNumeralError 잇�況 件劍�ヴ, 그↔鋼 그 鰥휸� 獵� �맑� �健맑≠ �ヴ靴タ ↔健�, 그甦밀 그 �맑�ュ ���ヴ.
3 ��, 匯� 寧흴 建悚 �맑�ュ ���ヴ. 健 穢깍 ���鋼 �靴≠ �맑� �健맑況 梟� ┐ �靴≠ 휸、� � ��タ 匯� ↔槪 寧��ヴ .
4 그靴� 이�� �暎 맸�鋼 그 �� “OK” 읒∽頌 둥껍 。ヴ; 그↔鋼 匯� �맑�≠ ��� ┐ unittest 匯�읒 ��윈 �悚들ヴ.
Note
윈壽솥� 匯� �맑�≠ ��� ┐, ��槪 燁���.

5.11. �그況 庚靴��

윈壽솥健 �묽槪 ヴ�윈 �□�乾 傑� �맑�況 虔뭡�淞� �윔舡읒도 숄깬��, �그ュ 件�祿ヴ. 寧ュ “bug”頌 朗�槪 �藜�ュ≠? �그ュ 윈壽솥健 껍曳�� 虔뭡� �健 꼬ュ �맑� �健맑健ヴ.

Example 5.22. The bug

>>> import roman5
>>> roman5.fromRoman("") 1
0
1 ���ュ≠? 健�� 뭏�읒밀 �靴ュ � 珞腱읽健 傑湧� 頌譁 밝腱況 瑩↑�� 胛� 그 穢깍 ���읒 件��ュ ↔槪 숩뀜ヴ. 腱, ��祿 ↔鋼 健↔鋼 그 穢깍 ���� �暎 ��읒 ��윈 윈�尤 �健�ュ ↔健ヴ. 그靴� 그↔鋼 �그健ヴ; 傑湧� 頌譁 밝腱況 ���� 꿩ュ ヴ患 �┱ 읓뱃�乾 珞腱�� 譁�≠�頌 �  健 InvalidRomanNumeralError 잇�況 件劍�, � 珞腱읽槪 �靴ュ 읏�ヴ.

그 �그況 �휸�� �읒, 그靴� 그↔槪 �穢�� �읒, 윈壽솥鋼 ��況 �ュ, 그靴�윈 그 �그況 잇맸� �ュ �맑� �健맑況 虔뭡�윈꺌梟 �ヴ.

Example 5.23. Testing for the bug (romantest61.py)

class FromRomanBadInput(unittest.TestCase):

    # previous test cases omitted for clarity (they haven't changed)

    def testBlank(self):
        """fromRoman should fail with blank string"""
        self.assertRaises(roman.InvalidRomanNumeralError, roman.fromRoman, "") 1
1 윈�읒 ��尤 。�� ��≠ �ヴ. fromRoman槪 � 珞腱읽頌 繇��� 그靴� 그↔健 InvalidRomanNumeralError 잇�況 件劍�ュ� 蟯乾��. �淞� 쇰솥健�� �그況 黔ュ ↔健ヴ; 健靈 �靴ュ 그↔읒 ��윈 꿱� �劍�頌, 그↔槪 胛� �맑�ュ 맞� 쇰솥健ヴ.

�靴� ��ュ �그況 ≠�� �劍�頌, 그靴� 健靈 �靴ュ 健 �그況 �맑��ュ �맑� �健맑況 ≠�� �劍�頌, 그 �맑� �健맑ュ ��� ↔健ヴ:

Example 5.24. Output of romantest61.py against roman61.py

fromRoman should only accept uppercase input ... ok
toRoman should always return uppercase ... ok
fromRoman should fail with blank string ... FAIL
fromRoman should fail with malformed antecedents ... ok
fromRoman should fail with repeated pairs of numerals ... ok
fromRoman should fail with too many repeated numerals ... ok
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

======================================================================
FAIL: fromRoman should fail with blank string
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage6\romantest61.py", line 137, in testBlank
    self.assertRaises(roman61.InvalidRomanNumeralError, roman61.fromRoman, "")
  File "c:\python21\lib\unittest.py", line 266, in failUnlessRaises
    raise self.failureException, excName
AssertionError: InvalidRomanNumeralError
----------------------------------------------------------------------
Ran 13 tests in 2.864s

FAILED (failures=1)

健靈 �靴ュ 그 �그況 �� � �ヴ.

Example 5.25. Fixing the bug (roman62.py)

def fromRoman(s):
    """convert Roman numeral to integer"""
    if not s: 1
        raise InvalidRomanNumeralError, 'Input can not be blank'
    if not re.search(romanNumeralPattern, s):
        raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s

    result = 0
    index = 0
    for numeral, integer in romanNumeralMap:
        while s[index:index+len(numeral)] == numeral:
            result += integer
            index += len(numeral)
    return result
1 읫曳 듬 娛� ��梟健 ���ヴ: � 珞腱읽槪 胛� �맸�乾 瑩↑, 그靴� raise 밀�珞.

Example 5.26. Output of romantest62.py against roman62.py

fromRoman should only accept uppercase input ... ok
toRoman should always return uppercase ... ok
fromRoman should fail with blank string ... ok 1
fromRoman should fail with malformed antecedents ... ok
fromRoman should fail with repeated pairs of numerals ... ok
fromRoman should fail with too many repeated numerals ... ok
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

----------------------------------------------------------------------
Ran 13 tests in 2.834s

OK 2
1 그 ×� 珞腱읽 �맑� �健맑ュ 健靈 ���ヴ, 그甦밀 그 �그ュ ��倪ヴ.
2 ヴ患 匯� �맑� �健맑�鋼 윈�尤 ���ヴ, 그↔鋼 健 �그 �穢健 ヴ患 �┱ ↔도 淮≠├靴� 꿩뀜舡槪 �藜�ヴ. ��槪 燁���.

健塑 籃�劍頌 ���ヴ� �밀 �그況 ��ュ ↔健 � 릴∽ ��ュ 꿩ュヴ. (健↔�  鋼) 。�� �그�鋼 。�� �맑� �健맑況 �깬�ヴ; 손�� �그�鋼 손�� �맑� �健맑況 �깬� ↔健ヴ. �맑�-燁� 橒±읒밀ュ, �그況 �穢�ュ ↔健 맸。健 皇健 �靴ュ �健 숩件�도 匯患ヴ, ���� 윈壽솥鋼 (�맑� �健맑況 虔뭡�� 胛�윈) 그 �그≠ 朗�乾� ��頌 獵�獵� 寧읽�꺌梟 �� 그 �그 腱譴況 �穢�꺌�� ┐珞健ヴ. 그靴� 寧밀 梟� 그 �맑� �健맑≠ �、 ���� 꿩ュヴ�, 윈壽솥鋼 그 �穢健 剛鰥��ュ� 껍レ� 그 �맑� �健맑 腱譴≠ �그況 ≠�� �ュ� 꿱껍 숩껍꺌梟 �ヴ. 그峀�梟, �균읒ュ, 健 �맑��ュ ��잴 �맑� 良ュ �� �健� 꽜劍頌-그靴�-딘頌 �簫鋼 그 腱譴頌 健鋸健 �ヴ, ���� 그↔鋼 �그�健 � 纜읒 穢蟯�∽ �穢� ≠�뭡健 � 皇도刷 �윈 �� ┐珞健ヴ. ��, 윈壽솥鋼 匯� �맑� �健맑況 윈壽솥� �頌� �健맑頌, 릴∽ �-��� � �劍�頌 윈壽솥鋼 �頌� ��況 �穢� ┐ 잇�� ��況 淮≠�奐 ≠�뭡健 雨꽉 � �∽들ヴ. 읫ヌ� 傑� �맑�ュ 蘆件� 耘깃 �맑�健ヴ.

5.12. �깬獵� 순±槪 庚靴��

윈壽솥� �∥槪 ┫ 力ヲ읒 꾄壽├靴� ≠胛 그靴� �� �ュ 잼맑  鋼 뱉華臘�∽ 朗밀� ↔�頌 �珞�윈 穢蟯� �깬獵�槪 그�읒∽밀 淡�蘆ュ 윈壽솥� �묽� �悚읒도 숄깬��, �깬獵�鋼 순±� ↔健ヴ. �쇰솥� �∥�鋼 그�健 �靈頌 숩� ���ュ 그�健 읏�ュ ↔槪 꿱� 鰥�ヴ, 그靴� 꿱��도, 그�鋼 읏�ュ ↔槪 獵�獵� 穢蟯�∽ ��� 梟� 穢도頌 寧읽�ュ ↔읒 鋸밍�� 鰥�ヴ. 그靴� 鋸밍�ヴ� ���도, 그�鋼 ヴ舡 ��┐읒ュ �倻� � 皇鋼 ↔槪 읏� ↔健ヴ. 그甦밀 �깬獵�健 순±득읒 會偈� 윈壽솥� �맑� �健맑況 ″�� � �도刷 影���.

잇況 ��, �靴� 頌譁 밝腱 순橒 ��� �胛況 蟯���況 읏�ヴ� ≠穢�숩�. �─� 珞腱도 뭐纜槪 競��윈 �손� � 꼬ヴュ 그 깍�槪 ���ュ≠? 腱, 그 頌譁乾�鋼 �湍健 그 깍�읒 잇�況 梟��밀 4⌒� M 珞腱況 件�頌 寧읽�윈 4000槪 ���淞� �윔ヴ. 梟� �靴≠ 健峀∽ 순±槪 ��, �靴ュ 순橒≠�� 밝腱� �胛況 1..3999읒밀 1..4999劍頌 蟯�� � �槪 ↔健ヴ. 그壽寧 晄�, �靴ュ �靴� �맑� �健맑읒 �。� 순±槪 � ��≠ �ヴ.

Example 5.27. Modifying test cases for new requirements (romantest71.py)

윈壽솥健 껍曳 그峀∽ �� 鰥�ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

import roman71
import unittest

class KnownValues(unittest.TestCase):
    knownValues = ( (1, 'I'),
                    (2, 'II'),
                    (3, 'III'),
                    (4, 'IV'),
                    (5, 'V'),
                    (6, 'VI'),
                    (7, 'VII'),
                    (8, 'VIII'),
                    (9, 'IX'),
                    (10, 'X'),
                    (50, 'L'),
                    (100, 'C'),
                    (500, 'D'),
                    (1000, 'M'),
                    (31, 'XXXI'),
                    (148, 'CXLVIII'),
                    (294, 'CCXCIV'),
                    (312, 'CCCXII'),
                    (421, 'CDXXI'),
                    (528, 'DXXVIII'),
                    (621, 'DCXXI'),
                    (782, 'DCCLXXXII'),
                    (870, 'DCCCLXX'),
                    (941, 'CMXLI'),
                    (1043, 'MXLIII'),
                    (1110, 'MCX'),
                    (1226, 'MCCXXVI'),
                    (1301, 'MCCCI'),
                    (1485, 'MCDLXXXV'),
                    (1509, 'MDIX'),
                    (1607, 'MDCVII'),
                    (1754, 'MDCCLIV'),
                    (1832, 'MDCCCXXXII'),
                    (1993, 'MCMXCIII'),
                    (2074, 'MMLXXIV'),
                    (2152, 'MMCLII'),
                    (2212, 'MMCCXII'),
                    (2343, 'MMCCCXLIII'),
                    (2499, 'MMCDXCIX'),
                    (2574, 'MMDLXXIV'),
                    (2646, 'MMDCXLVI'),
                    (2723, 'MMDCCXXIII'),
                    (2892, 'MMDCCCXCII'),
                    (2975, 'MMCMLXXV'),
                    (3051, 'MMMLI'),
                    (3185, 'MMMCLXXXV'),
                    (3250, 'MMMCCL'),
                    (3313, 'MMMCCCXIII'),
                    (3408, 'MMMCDVIII'),
                    (3501, 'MMMDI'),
                    (3610, 'MMMDCX'),
                    (3743, 'MMMDCCXLIII'),
                    (3844, 'MMMDCCCXLIV'),
                    (3888, 'MMMDCCCLXXXVIII'),
                    (3940, 'MMMCMXL'),
                    (3999, 'MMMCMXCIX'),
                    (4000, 'MMMM'),                                       1
                    (4500, 'MMMMD'),
                    (4888, 'MMMMDCCCLXXXVIII'),
                    (4999, 'MMMMCMXCIX'))

    def testToRomanKnownValues(self):
        """toRoman should give known result with known input"""
        for integer, numeral in self.knownValues:
            result = roman71.toRoman(integer)
            self.assertEqual(numeral, result)

    def testFromRomanKnownValues(self):
        """fromRoman should give known result with known input"""
        for integer, numeral in self.knownValues:
            result = roman71.fromRoman(numeral)
            self.assertEqual(integer, result)

class ToRomanBadInput(unittest.TestCase):
    def testTooLarge(self):
        """toRoman should fail with large input"""
        self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, 5000) 2

    def testZero(self):
        """toRoman should fail with 0 input"""
        self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, 0)

    def testNegative(self):
        """toRoman should fail with negative input"""
        self.assertRaises(roman71.OutOfRangeError, roman71.toRoman, -1)

    def testDecimal(self):
        """toRoman should fail with non-integer input"""
        self.assertRaises(roman71.NotIntegerError, roman71.toRoman, 0.5)

class FromRomanBadInput(unittest.TestCase):
    def testTooManyRepeatedNumerals(self):
        """fromRoman should fail with too many repeated numerals"""
        for s in ('MMMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):     3
            self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s)

    def testRepeatedPairs(self):
        """fromRoman should fail with repeated pairs of numerals"""
        for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
            self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s)

    def testMalformedAntecedent(self):
        """fromRoman should fail with malformed antecedents"""
        for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
                  'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
            self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, s)

    def testBlank(self):
        """fromRoman should fail with blank string"""
        self.assertRaises(roman71.InvalidRomanNumeralError, roman71.fromRoman, "")

class SanityCheck(unittest.TestCase):
    def testSanity(self):
        """fromRoman(toRoman(n))==n for all n"""
        for integer in range(1, 5000):                                    4
            numeral = roman71.toRoman(integer)
            result = roman71.fromRoman(numeral)
            self.assertEqual(integer, result)

class CaseCheck(unittest.TestCase):
    def testToRomanCase(self):
        """toRoman should always return uppercase"""
        for integer in range(1, 5000):
            numeral = roman71.toRoman(integer)
            self.assertEqual(numeral, numeral.upper())

    def testFromRomanCase(self):
        """fromRoman should only accept uppercase input"""
        for integer in range(1, 5000):
            numeral = roman71.toRoman(integer)
            roman71.fromRoman(numeral.upper())
            self.assertRaises(roman71.InvalidRomanNumeralError,
                              roman71.fromRoman, numeral.lower())

if __name__ == "__main__":
    unittest.main()
1 그 梧��ュ 꿱淞玲 』�鋼 순±�� 꿩ュヴ (그↔�鋼 윈�尤 �맑�� 健傑≠ �ュ 』�健ヴ), 그壽寧 �靴ュ 4000 �胛읒밀 �。槪 � 偈≠� ��≠ �ヴ. 윈�읒 寧ュ (≠� 兩鋼) 4000, (듬纜�頌 兩鋼) 4500, (≠� �) 4888, 그靴� (≠� �) 4999況 �� 맸�ヴ.
2 “�』 建悚”� 穢�ュ 순±��ヴ. 健 �맑�ュ toRoman4000劍頌 繇��� 그靴� 읒壽況 �ヴ誦�ヴ; 健靈 4000-4999ュ 霓鋼 』�健�頌, �靴ュ 健↔槪 5000�� 粱� 이奐 ��≠ �ヴ.
3 “樓朗 皇鋼 �손들 밝腱�”� 穢� �� 순±��ヴ. 健 �맑�ュ fromRoman'MMMM'劍頌 繇��� 읒壽況 �ヴ誦�ヴ; 健靈 MMMMュ 傑湧� 頌譁 밝腱頌 윈���頌, �靴ュ 健↔槪 'MMMMM'�� 粱� 이奐 ��≠ �ヴ.
4 京� 瑩↑� �뱉珞腱 瑩↑鋼, 1읒밀 3999��� �胛꿴읒 �ュ 匯� 밝腱�槪 耘둥健�ヴ. 그 �胛ュ 健靈 蟯���劍�頌, 健壽� for 耘둥健�鋼 �� 4999�� 이�≠도刷 ″�� ��≠ �ヴ.

健靈 �靴� �맑� �健맑ュ �靴� �頌� �깬獵�劍頌 �頌�倪ヴ, 그壽寧 �靴� ��ュ 그峀� 꿩ヴ, 그甦밀 �靴ュ �靴� �맑� �健맑燁 �。鋼 ���靴�� 잇��ヴ.

Example 5.28. Output of romantest71.py against roman71.py


fromRoman should only accept uppercase input ... ERROR        1
toRoman should always return uppercase ... ERROR
fromRoman should fail with blank string ... ok
fromRoman should fail with malformed antecedents ... ok
fromRoman should fail with repeated pairs of numerals ... ok
fromRoman should fail with too many repeated numerals ... ok
fromRoman should give known result with known input ... ERROR 2
toRoman should give known result with known input ... ERROR   3
fromRoman(toRoman(n))==n for all n ... ERROR                  4
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
1 �靴� �뱉珞腱 瑩↑鋼 健靈 ���ヴ. ���� 그↔鋼 1쇰� 4999�� 耘둥健 ��梟, toRoman鋼 읫曳 1읒밀 3999��� 밝腱梟槪 良껍�健� ┐珞健ヴ, 그甦밀 그 �맑� �健맑≠ 4000읒 도マ�腱 譁腱 그↔鋼 ��� ↔健ヴ.
2 fromRoman� 꿱淞玲 』 �맑�ュ 'MMMM'읒 도マ�腱 譁腱 ��� ↔健ヴ, ���� fromRoman鋼 윈�尤 健↔健 朗湧� 頌譁 밝腱�� 휸、�� ┐珞健ヴ.
3 toRoman� 꿱淞玲 』 �맑�ュ 4000읒 도マ�腱 譁腱 ��� ↔健ヴ, ���� toRoman鋼 윈�尤 健↔健 �胛況 諒�祿 ↔健�� 휸、�� ┐珞健ヴ.
4 京� 瑩↑ 을맸 4000읒 도マ�腱 譁腱 ��� ↔健ヴ, ���� toRoman鋼 윈�尤 健↔健 �胛況 諒�祿 ↔健�� 휸、�� ┐珞健ヴ.

======================================================================
ERROR: fromRoman should only accept uppercase input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage7\romantest71.py", line 161, in testFromRomanCase
    numeral = roman71.toRoman(integer)
  File "roman71.py", line 28, in toRoman
    raise OutOfRangeError, "number out of range (must be 1..3999)"
OutOfRangeError: number out of range (must be 1..3999)
======================================================================
ERROR: toRoman should always return uppercase
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage7\romantest71.py", line 155, in testToRomanCase
    numeral = roman71.toRoman(integer)
  File "roman71.py", line 28, in toRoman
    raise OutOfRangeError, "number out of range (must be 1..3999)"
OutOfRangeError: number out of range (must be 1..3999)
======================================================================
ERROR: fromRoman should give known result with known input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage7\romantest71.py", line 102, in testFromRomanKnownValues
    result = roman71.fromRoman(numeral)
  File "roman71.py", line 47, in fromRoman
    raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s
InvalidRomanNumeralError: Invalid Roman numeral: MMMM
======================================================================
ERROR: toRoman should give known result with known input
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage7\romantest71.py", line 96, in testToRomanKnownValues
    result = roman71.toRoman(integer)
  File "roman71.py", line 28, in toRoman
    raise OutOfRangeError, "number out of range (must be 1..3999)"
OutOfRangeError: number out of range (must be 1..3999)
======================================================================
ERROR: fromRoman(toRoman(n))==n for all n
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\docbook\dip\py\roman\stage7\romantest71.py", line 147, in testSanity
    numeral = roman71.toRoman(integer)
  File "roman71.py", line 28, in toRoman
    raise OutOfRangeError, "number out of range (must be 1..3999)"
OutOfRangeError: number out of range (must be 1..3999)
----------------------------------------------------------------------
Ran 13 tests in 2.213s

FAILED (errors=5)

健靈 �靴ュ 그 �頌� �깬獵�┐珞읒 ���ュ �맑� �健맑況 ≠�� �劍�頌, �靴ュ 그 ��況 �穢�윈 그 �맑� �健맑잴 獵優맸�ュ ↔읒 ��윈 휸、� � �ヴ. (윈壽솥健 庚舡劍頌 傑� �맑�況 ���� 맸虔� ┐ ���꺌� � ≠�ュ �맑� � 그 ��ュ 그 �맑� �健맑숩ヴ 據�頌 “晄�(ahead)”≠ 껍レ�ュ ↔健ヴ. 그 ��ュ 윈�尤 딘健�ュ ��梟, 윈壽솥鋼 윈�尤 欖≠況 虔돛맸�� �劍�, 그↔健 그 �맑� �健맑況 �� �ュ 뮈。, 윈壽솥鋼 ��槪 燁��ヴ.)

Example 5.29. Coding the new requirements (roman72.py)

"""Convert to and from Roman numerals"""
import re

#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))

def toRoman(n):
    """convert integer to Roman numeral"""
    if not (0 < n < 5000):                                                         1
        raise OutOfRangeError, "number out of range (must be 1..4999)"
    if int(n) <> n:
        raise NotIntegerError, "decimals can not be converted"

    result = ""
    for numeral, integer in romanNumeralMap:
        while n >= integer:
            result += numeral
            n -= integer
    return result

#Define pattern to detect valid Roman numerals
romanNumeralPattern = '^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$' 2

def fromRoman(s):
    """convert Roman numeral to integer"""
    if not s:
        raise InvalidRomanNumeralError, 'Input can not be blank'
    if not re.search(romanNumeralPattern, s):
        raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s

    result = 0
    index = 0
    for numeral, integer in romanNumeralMap:
        while s[index:index+len(numeral)] == numeral:
            result += integer
            index += len(numeral)
    return result
1 toRoman鋼, �胛 瑩↑읒밀, 읫曳 �寧� 虔鋼 순±梟槪 ��頌 �ヴ. �靴≠ 0 < n < 4000槪 瑩↑�タ ≒읒밀, �靴ュ 健靈 0 < n < 5000況 瑩↑�ヴ. 그靴� �靴ュ �靴≠ 件劍�ュ (raise) 그 읒壽 回맸�況 순±�윈 그 �頌� 閻�≠�� �胛(1..3999��읒 1..4999)況 �윳�ヴ. �靴ュ 그 ��� 寧蛔� ��읒 ��밀ュ 껍朗塑 순±도 � ��≠꼬ヴ; 그↔鋼 健藜 그 �頌� �健맑�槪 庚靴�ヴ. (그↔鋼 腱�健 烙¨� 、、� 絹읒 ��윈 �寧∽ 'M'槪 偈≠�ヴ; 4000健 ��, 그↔鋼 'MMMM'槪 �껍 冷 ↔健ヴ. 健�읒ュ 그↔健 健峀∽ �� 꿩鋼 傑件� 健傑ュ �靴≠ �胛 瑩↑劍頌 �맸�劍頌 그↔槪 燁��윔� ┐珞健ヴ.)
2 �靴ュ fromRoman읒 �� 순±槪 ≠� ��≠ 꼬ヴ. 傑件� 순±健�� romanNumeralPattern읒 �� ↔乾뎬; 梟� 윈壽솥健 腱뭐尤 ��숩�, �靴≠ � ヴ患 묽��乾 M槪 그 穢깍 ���� 憬 纜櫻 뭏�읒 偈≠�ヴュ ↔槪 꿱∽ � ↔健ヴ. 健↔鋼 3 ��읒 4⌒� M 珞腱�� ��� ↔健ヴ, 그↔鋼 �靴≠ 3999 ��읒 4999� 돛�� 頌譁 밝腱況 ��� ↔健�ュ ↔槪 ┥�ヴ. �靈� fromRoman ��ュ 잽�尤 件��健ヴ; 그↔鋼 �� �손�ュ 頌譁 밝腱�槪 �ヴ淞밀, �譁寧 皇健 그↔�健 �손�ュ� �濾�� 꿩�밀, 그↔�槪 偈≠� �ュヴ. 그↔健 健�읒ュ 'MMMM'槪 庚靴�� 꿩鋼 傑件� 健傑ュ �靴≠ 그 穢깍 ��� �� 羊禮�頌 �맸�劍頌 그↔槪 燁��윔� ┐珞健ヴ.

健 듬 ⌒� 虔鋼 순±健 �靴≠ ��� 匯� ↔健�ュ ↔健 윈壽솥鋼 ��맑壽� � �ヴ. 腱, 蘆恍槪 ◎健 ◎�頌 礪� 譁�; 윈壽솥 맑맑頌 꿱껍숩�:

Example 5.30. Output of romantest72.py against roman72.py

fromRoman should only accept uppercase input ... ok
toRoman should always return uppercase ... ok
fromRoman should fail with blank string ... ok
fromRoman should fail with malformed antecedents ... ok
fromRoman should fail with repeated pairs of numerals ... ok
fromRoman should fail with too many repeated numerals ... ok
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

----------------------------------------------------------------------
Ran 13 tests in 3.685s

OK 1
1 匯� �맑� �健맑ュ ���ヴ. ��槪 丸偈��.

�□�乾 傑� �맑�≠ ┥�ュ ↔鋼 “寧況 礪劍맸읫”�� 恍�ュ �頌그甦蛔읒∽ �梧� ��≠ 꼬ヴュ ↔健ヴ.

5.13. �솥�

�□�乾 傑� �맑�읒 ��윈 ≠� 霓鋼 ↔鋼 윈壽솥� 匯� �맑� �健맑≠ ���윔槪 ┐ 윈壽솥健 ニ臘ュ \穢健 껍レ�, ���ュ �┱ ヴ患 �┶健 그�� ��況 淮��뀜ヴ� 윈壽솥槪 �祿� ┐읒 그靴� 윈壽솥鋼 �靈頌 윈壽솥健 그塑 ↔健 껍レ�ュ ↔槪 ��� � ��槪 ┐ ニ臘ュ 그 \穢도 껍レヴ. 傑� �맑�읒 ��윈 ≠� 霓鋼 ↔鋼 그↔健, 駑玗�∽ �솥�� � �ュ 腱傑況 윈壽솥읒∽ 影ヴュ ↔健ヴ.

�솥�ュ 虔돛�� �ュ ��況 ��밀, 그↔槪 �� 剛 虔돛�도刷 �ュ 庚靴�穢健ヴ. 숩�, “� 霓鋼 (better)” 健�ュ ↔鋼 “� �患 (faster)”槪 �藜�ュ뎬, 그峀�梟 그↔鋼 �� “� �鋼 回匯靴況 ���”槪 �藜� �도 ��, �ュ “� �鋼 뒵맑� �歲槪 ���”槪 �藜��寧, 玗鋼 �뮈�∽ “� �껍�∽”況 �藜� � �ヴ. 윈壽솥읒∽, 윈壽솥� �頌鹽�읒, 윈壽솥� ⌒烙橒±읒, 그↔健 �┱ �藜健�� 。읒, �솥�ュ 匯� �頌그少� ���乾 �∠읒 燁��ヴ.

윈�읒밀, “� 霓鋼 (better)”ュ “� �患 (faster)”槪 �藜�ヴ. 깬譴�劍頌 恍��, fromRoman ��ュ �靈頌 ��� 뱃도 숩ヴュ � ニ靴ヴ, 頌譁 밝腱況 ↑��� 胛�윈 �靴≠ ���, 그 ���� 뭡≠� 穢깍 ��� ┐珞健ヴ. 그 穢깍 ���槪 껍잇 꼬� �靴淞� �悚�ュ ↔鋼 껍譁도 ≠�≠ 꼬槪 ↔  ヴ (그↔鋼 ��� 虔꾑件 �도 ��, 그靴� 그 뭡�≠ � �花∽ 들ヴュ 숩�도 꼬ヴ), 그壽寧 �靴ュ 그 穢깍 ���槪 藜靴 �裔�(precompile)劍頌� 그 ��� 뱃도況 �件 � �ヴ.

Example 5.31. Compiling regular expressions

>>> import re
>>> pattern = '^M?M?M?$'
>>> re.search(pattern, 'M')               1
<SRE_Match object at 01090490>
>>> compiledPattern = re.compile(pattern) 2
>>> compiledPattern
<SRE_Pattern object at 00F06E28>
>>> dir(compiledPattern)                  3
['findall', 'match', 'scanner', 'search', 'split', 'sub', 'subn']
>>> compiledPattern.search('M')           4
<SRE_Match object at 01104928>
1 健↔鋼 �靴≠ 健�읒 셜 그 깬珞健ヴ: re.searchュ 穢깍 ���槪 �寧� 珞腱읽(pattern)頌 그靴� 그↔� 件�맸�섰 珞腱읽('M')槪 ��ヴ . 梟� 그 ��健 件���, 그 ��ュ 件� ∥譴況 �橒�ュ뎬 그 ∥譴읒∽ 蘿�숩� 穢蟯�∽ 朗�健 件���� �┍∽ 件���ュ� 꿱껍 섰 � �ヴ.
2 健↔鋼 그 �頌� 깬珞健ヴ: re.compile鋼 穢깍 ���槪 珞腱읽頌 ��� �� ∥譴況 �橒�ヴ. 윈�읒ュ 件��ュ 껍朗塑 珞腱읽도 꼬舡槪 ����. 穢깍 ���槪 �裔�ュ ↔鋼 그↔槪 ('M'�  鋼) �┱ �穢� 珞腱읽읒 件�맸�ュ ↔�ュ 껍朗塑 ��健 꼬ヴ; 그↔鋼 읫頌� 그 穢깍 ��� 腱譴읒 �蘇들ヴ.
3 re.compile頌쇰� �橒들, 그 �裔들 �� ∥譴ュ �。� 傑��-숩健ュ ���槪 ≠玲ヴ. (searchsub 鋼) re 匯�읒밀 曳閻�劍頌 ��≠�� ↔�健 ��들ヴ.
4 그 �裔들 �� ∥譴� search ��況 珞腱읽 'M'劍頌 繇��ュ ↔鋼 re.search況 그 穢깍 ���� 그 珞腱읽 'M' 듬 ⌒況 ≠�� 繇��ュ ↔�  鋼 件槪 マ뭡�ヴ. 읫曳 �� �, �花∽. (��, re.search ��ュ �뮈�∽ 그 穢깍 ���槪 �裔�� 그靴� 그 ��頌 寧장 �� ∥譴� search 回��況 윈壽솥 ��읒 繇��ヴ.)
Note
윈壽솥健 � 纜健� 穢깍 ���槪 ���淞� � ┐譁ヴ, 윈壽솥鋼 그↔槪 �裔�윈 �� ∥譴況 寓돗�도刷 �윈꺌梟 ��, 그靴�ュ 그 �� ∥譴읒 �ュ 回���槪 曳閻�劍頌 繇��윈꺌梟 �ヴ.

Example 5.32. Compiled regular expressions in roman81.py

윈壽솥健 껍曳 그峀∽ �� 꿩뀜ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � 꼬ヴ (Windows, UNIX, Mac OS).

# toRoman and rest of module omitted for clarity

romanNumeralPattern = \
    re.compile('^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$') 1

def fromRoman(s):
    """convert Roman numeral to integer"""
    if not s:
        raise InvalidRomanNumeralError, 'Input can not be blank'
    if not romanNumeralPattern.search(s):                                    2
        raise InvalidRomanNumeralError, 'Invalid Roman numeral: %s' % s

    result = 0
    index = 0
    for numeral, integer in romanNumeralMap:
        while s[index:index+len(numeral)] == numeral:
            result += integer
            index += len(numeral)
    return result
1 健↔鋼 ��尤 �며� 숩乾ヴ, 그壽寧 ��鋼 皇鋼 ↔健 순±��ヴ. romanNumeralPatternュ 健靈 珞腱읽健 껍レヴ; 그↔鋼 re.compile劍頌쇰� �橒들 �� ∥譴健ヴ.
2 그↔鋼 �靴≠ romanNumeralPattern읒 �ュ 回��況 曳閻�劍頌 繇�� � �ヴュ ↔槪 �藜�ヴ. 健↔鋼 re.search槪 �纜 繇��ュ ↔숩ヴ ��, � �花∽ � ↔健ヴ. 그 穢깍 ���鋼 그 匯�健 庚舡劍頌 �建� ┐ �纜 �裔�� romanNumeralPattern읒 ��들ヴ; 그靴�ュ, �靴≠ fromRoman槪 繇�� ┐譁ヴ, �靴ュ 蘿 亂읒밀 件�寧ュ �┱ 。閻�乾 ��도 �� 꼬健, �맸 그 建悚 珞腱읽槪 그 穢깍 ���읒 會偈� 섰 � �ヴ.

그甦밀 �靴� 穢깍 ���槪 �裔�� �譁寧 � �患≠? 윈壽솥 맑맑頌 꿱껍숩�:

Example 5.33. Output of romantest81.py against roman81.py

.............          1
----------------------------------------------------------------------
Ran 13 tests in 3.385s 2

OK                     3
1 윈�� �弄��읒밀 ����: 健 纜읒, 寧ュ 그 傑� �맑�況 -v 묽��� 꼬健 ���ヴ, 그甦밀 、 �맑�읒 �� 잽�� 珞밀優 珞腱읽 (doc string) ��읒, �靴ュ ���ュ 、 �맑�읒 ��윈 � ⌒� 瑩梟槪 �ュヴ. (梟� �맑�≠ ����, �靴ュ F況 寓돗�∽ � ↔健ヴ, 그靴� 梟� 그↔健 읒壽況 ≠玲ヴ�, �靴ュ E況 �∽ � ↔健ヴ. �靴ュ 、、� ��잴 읒壽읒 ��윈 윈�尤 잽�� 을 偈�槪 傑�� ↔健�, 그甦밀 �靴ュ �─� 珞靈도 偈�� 蘆淞〈 �≠ �ヴ.)
2 �靴ュ 13⌒� �맑�況 그 穢깍 ���槪 藜靴 �裔�� 꿩鋼 3.685 잴 �귑�윈, 3.385競 梟읒 ���ヴ. 그↔鋼 ���劍頌 8%� ⌒묽健ヴ, 그靴� ��� ↔鋼 그 傑� �맑� 돛꿴읒 뱉��ュ �쇰솥� 맸。鋼 ヴ患 件�槪 �ュ뎬읒 뱉�들ヴュ ↔健ヴ. (⌒샥�劍頌, 寧ュ 그 穢깍 ���槪 그 腱譴頌, 그 傑� �맑�� 寧蛔�잴 ┨�밀, 맸。 結穢槪 �윔ヴ, 그靴� 蘆≠ 烙¨� ↔鋼 健 穢깍 ���槪 �裔�� 그 search況 �귀�劍頌 54%穢도 뱃도 �≠맸�ヴュ ↔健�ヴ.) 그塑 。�� �穢劍頌ュ 霓鋼 ��健ヴ.
3 읫!, 그靴� 윈壽솥健 ±�� 譁� 꿩槪 ±�頌, �靴� 穢깍 ���槪 藜靴 �裔�ヴ� �밀 �┱ ↔도 �권�� 꿩뀜ヴ, 그靴� �靴ュ 그↔槪 ��� 숩윔ヴ.

蘆≠ 맸도�숩� 멸鋼 � �寧� �� ��優≠ �ヴ. 穢깍 ��� 깬珞� 손�뭡槪 �腱�,  鋼 ��槪 虔뭡�ュ뎬 � ⌒ 健�� 籃輛健 �ヴ� �도 ��梟� 件鋼 껍ヱ ↔健ヴ. comp.lang.python읒밀 健 匯�읒 �� �。� �速�읒, �┱ �┶� 靈꿴槪 良껍�윈밀 寧ュ 그 묽��乾 �손들 珞腱읽 ��읒 {m,n} 깬珞槪 ����況 맸도�윔ヴ.

Example 5.34. roman82.py

윈壽솥健 껍曳 그峀∽ �� 鰥�ヴ�, 윈壽솥鋼 健↔� 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

# rest of program omitted for clarity

#old version
#romanNumeralPattern = \
#   re.compile('^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$')

#new version
romanNumeralPattern = \
    re.compile('^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$') 1
1 �靴ュ M?M?M?M?M{0,4}頌 ���윔ヴ. � ヴ  鋼 ↔槪 �藜�ヴ: “0읒밀 4⌒ ��� M 珞腱況 件�맸�ヴ”. �며�∽, C?C?C?C{0,3}健 ��ヴ (“0 읒밀 4 ⌒��� C 珞腱況 件�맸�ヴ”) 그靴� �� X 그靴� I읒 譁�≠�ヴ.

그 穢깍 ���� 健塑 ��ュ �。 � 兩ヴ (그峀�梟 居�ュ 릴� 꿩ヴ). � 珞靈ュ, 그↔鋼 �譁寧 � �患≠?

Example 5.35. Output of romantest82.py against roman82.py

.............
----------------------------------------------------------------------
Ran 13 tests in 3.315s 1

OK                     2
1 ���劍頌, 그 傑� �맑�ュ 健塑 ��� 穢깍���劍頌 2% � �花∽ ��들ヴ. 그 穢도꺌 �寧∽ 숩健�ュ 꿩ュヴ, 그壽寧 ��� ↔鋼 search ��ュ �譴 傑� �맑�읒밀 虔鋼 쇰솥健�ュ ↔健ヴ; �쇰솥� 맸。鋼 ヴ患 件�槪 �ュ뎬 뱉�들ヴ. (⌒샥�劍頌 , 寧ュ 그 穢깍 ���梟槪 맸。-結穢� 숩뀜ヴ, 그靴� search ��≠ 健 깬珞劍頌 11% �花ヴュ ↔槪 꿱뀜ヴ.) 그 穢깍 ���槪 藜靴 �裔�듬� 健 �頌� 깬珞槪 ���� 胛�윈 그↔� 件쇰솥槪 �虔뭡�劍頌�, �靴ュ 그 穢깍 ���� ���悚槪 60% 健� ⌒묽�윔�, 그靴� 그 �譴 傑� �맑�� ��� 뭡�槪 10% 健� ⌒묽�윔ヴ.
2 �� 뭡� �≠ 숩ヴ도 �� 燁�� ↔鋼 그 匯�健 윈�尤 잽섀�∽ 虔돛�ヴュ ��健ヴ. 健↔健 力頌 健�읒 蘆≠ 健꺌� �タ 그 腱傑健ヴ: ���� 腱傑, 순±��寧, 玗鋼 그 �┱ 獵、도 �虔뭡� 腱傑 그靴� 그 �穢燁읒 윈壽솥健 ヴ患 �┱ ↔도 ��靴� 꿩뀜ヴュ ↔槪 蟯乾�ュ 腱傑. 健↔鋼 ��� 그 腱譴 梟槪 胛�밀 棠巾꼬健 윈壽솥� ��況 ����ュ 籃暎健 껍レヴ; �靴ュ (“fromRoman槪 � �花∽ 梟�ュ”) 껍� �穢� ��槪 ≠倪劍�, 그靴� �靴≠ 그 �穢燁읒 �頌� �그況 健淡� �健�ュ 꿩뀜ュ�읒 ��윈 � 瑩� ��도 錄�� 꿩� �靴ュ 그 ��槪 マ뭡� � ��ヴ. .

寧ュ ヴ患 �寧梟 � ��� 숩� 멸ヴ, 그靴� 寧밀 寧ュ �솥�況 丸偈� 健 匯�槪 꿴穢맸� ↔健�� �뱃�ヴ. �靴≠ �손�밀 숩뀜�健, 穢깍 ���鋼 ��尤 祿휭�� � �� 그靴� ��尤 �花∽ �덱 숄≠��� � �ヴ. 寧ュ 6⌒�健 �祿�읒 ヴ맸 健 匯�읒 둥껍잴 그↔槪 숩��淞� �悚�� 멸�ュ 꿩ヴ. 蘿速, 그 �맑� �健맑ュ ���ヴ, 그甦밀 寧ュ 그↔健 虔돛�ヴュ ↔槪 꿴ヴ, 그壽寧 梟� 蘆≠ �┍∽ 그↔健 虔돛�ュ� 健��� 鰥�ヴ�, 寧ュ �頌� ��槪 偈≠��도, �頌� �그況 �穢��도, 그峀� 꿩劍� 그↔槪 傑�숩�� �도 꼬槪 ↔健ヴ. 珞밀優ュ ���劍頌 燁��ヴ, 그靴� �健�鋼 윈壽솥� 穢깍 ���槪 腱뭐�∽ 珞밀優�ュ 籃輛槪 靈×�ヴ.

Example 5.36. roman83.py

윈壽솥健 껍曳 그峀∽ �� 鰥�ヴ�, 윈壽솥鋼 健↔≠ 健 甄읒밀 ��들 ヴ患 잇靈�槪 蘆淞 良槪 � �ヴ (Windows, UNIX, Mac OS).

# rest of program omitted for clarity

#old version
#romanNumeralPattern = \
#   re.compile('^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$')

#new version
romanNumeralPattern = re.compile('''
    ^                   # beginning of string
    M{0,4}              # thousands - 0 to 4 M's
    (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
                        #            or 500-800 (D, followed by 0 to 3 C's)
    (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
                        #        or 50-80 (L, followed by 0 to 3 X's)
    (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
                        #        or 5-8 (V, followed by 0 to 3 I's)
    $                   # end of string
    ''', re.VERBOSE) 1
1 re.compile ��ュ 묽��乾 듬 纜櫻 ��況 �� � �ヴ, 그↔鋼 �寧 健�� �甦그� 裔�劍頌 그 �裔들 穢깍 ���읒 �� ヴ�� 묽���槪 靈��ヴ. 윈�읒 �靴ュ re.VERBOSE �甦그況 �穢�ュ뎬, 그↔鋼 �健�읒∽ 그 穢깍 ��� 腱譴 꿴읒 �乾-꿴 �묠健 �ヴュ ↔槪 �맸�ヴ. �묠�� 그 �순� ×�鋼 그 穢깍 ���� 쇰솥劍頌 。��� 꿩ュヴ; re.compile ��ュ 그 ���槪 �裔� ┐ �뮈�∽ 그↔� 匯듬況 諒�蘆 �禍ヴ. 健 �頌�, “밈��乾 (verbose)” ��鋼 잇� ��� 돛件�ヴ, 그壽寧 그↔鋼 솥�尤 �� 居� 릴ヴ.

Example 5.37. Output of romantest83.py against roman83.py

.............
----------------------------------------------------------------------
Ran 13 tests in 3.315s 1

OK                     2
1 健 �頌�, “밈��乾 (verbose)” ��鋼 健� ��� 穢蟯�∽ �  鋼 뱃도頌 ��들ヴ. ��, 그 �裔들 �� ∥譴ュ 돛件� ↔健ヴ, ���� re.compile ��ュ �靴≠ 偈≠� 匯� ↔�槪 諒�蘆 �靴� ┐珞健ヴ.
2 健 �頌�, “밈��乾 (verbose)” ��鋼 잇� ��� 譁�≠�頌  鋼 �맑� 匯듬況 ���ヴ. 껍朗↔도 순�� 꿩뀜ヴ, 6⌒� �읒 健 匯�읒 ヴ맸 둥껍장 그 �頌그甦蛔≠ 그 ��≠ �┍∽ 虔돛�ュ� 健��淞ュ ��� �耘읒 曳��ヴュ 瑩梟 홉�ュ 恍健ヴ.

5.14. � �

傑� �맑�ュ ∠悚� ⌒�劍頌, �據尤 깬���, 傑� ��槪 娛件 �도 �劍� 그靴� 匯� �� �頌鹽�읒밀 傑읓뭡槪 �≠맸� � �ヴ. �� 燁�� ↔鋼 傑� �맑�ュ 梟섐���도, ��맑壽� 珞靈 ���도, �ュ 鋼� �꿱도 껍レ�ュ ↔槪 健� �ュ ↔健ヴ. �禾� �맑� �健맑況 虔뭡�ュ ↔鋼 �貰ヴ, 그靴頌 그↔�槪 ��劍頌 傑��ュ ↔鋼 �� 깍喀槪 ��頌 �ヴ (�尤寧 믹ワ健 ���乾 �그 �穢槪 獪읽尤 �깬� ┐). 傑� �맑�ュ, ���乾 �맑�, �� �맑�, 그靴� ��腱 멨乾 �맑�況 ���, ヴ患 ��� �맑�� ��蘿健 껍レヴ. 그壽寧 傑� �맑�ュ 그騷 ��ヴ, 그靴� 剛 虔돛�ヴ, 그靴� 그↔健 虔돛�ュ ↔槪 숩∽ �� 윈壽솥鋼 그↔꼬健 도뎬譴 �┍∽ �屢ュ� ��∽ � ↔健ヴ.

健 �鋼 皇鋼 �셜槪 ヴ��ヴ, 그靴� ��� 皇鋼 쇰솥鋼 �健�-�穢�健� 꿩뀜ヴ. 皇鋼 꿇��槪 胛� 傑� �맑� �屬巾���健 �ヴ, 그 匯듬ュ 윈壽솥�健  鋼 �셜� ⌒��槪 健���況 �깬�ヴ:

��, 윈壽솥鋼 �꿴�∽ ヴ舡� �健�-�穢� ↔�槪 �� �윈꺌 �ヴ:

� 居�꺌 � ↔



[11] “寧ュ 匯� ↔槪 �쇰� � �ヴ, 傑玗梟 홉�ュ.” --Oscar Wilde


<< 靈 4 � HTML 庚靴 � 量 쇰 刷 >>