| << 4 ˌ HTML | >> |
˟ ˌ, “ ” ˞ ȓ 킯硒 ґ. ˼ ̋ 皡 Ղ, ղ ˟˂(before) ȓ .
ˌ 硒 . ۸ 븀皫 皦, ˼ . ˼ һ ռ ȍ ( “Copyright 1946” “Copyright MCMXLVI” ), ˼ Сһ ˼ ˂ ˂ ( “established 1888” “established MDCCCLXXXVIII” ) . ˼ ס굎 ˟ 禹 ˅. ס˼ ˂ ̸ ̦ ̫ ȍ ( ).
Ы, 7˂ ը ˅ վ ՠյ 禂͵ .
嵴 ˅:
˼ ˍ˅ ȍ 垂 ˅:
ݵ ˟ , ﹚˂ Dz ȗ ˅?
roman.py˂ 禡
ܲ
˟ ˂ ﹚ ȗ ˅ ˤ ˂Ղ, ˼ ȗ 굎 硒 : ݵ ﹚ ˂ 졒 硒 . ˼ : 皱 硒 .
嵴, Ҁ ˂ ﹚˂ , , 皡 ˅ ը. ˼ ˂ . ˼ ˤ 皡 ˅, ˞ unittest ݵ 翫.
| unittest 2.1 ȍ. 2.0 ȍ ס pyunit.sourceforge.net ˅. | |
˟̹ -秸 է ˟˂ ˌ . , ס굎 ( 챉 ˟ ), ȍ ס굎 ȸ즗. -˂ ˞ ˼ ̸ ˤ ̹ա , ס˼ ݵ է˂ :
˼ ﹚ ˤ ˟ ݵ, ס굎˼ roman.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()
ܲ
˂ ˌ ˞ ˼ Ҽ˞ . һ˂ ˅ ˂ ը 篫.
.... ˅
˟ , ˂ տ ̈. ˸ ˼ 禡 翫:
Example 5.2. testToRomanKnownValues
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)
˂ ﹚ ˼ 煲 ̾܂ ; һ 煲 ס굎 ܂ . ˂ ܡ 즗; ס굎˼ ȗ վ ܂.
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)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)
| unittest˂ TestCase assertRaises ϡ嵴, ס˼ ˸˂ 빚 ̑: ȗ졒 ˅ , ˅ ﹚, ﹚ 煫 빚. ( ﹚ ȗ˂ 빚 , Ы, ݵ assertRaises ҄ 煲, ס˼ 졒 ˅ ﹚ .) 졒 ˅ ˂ : toRoman ˞ ̉졒 (ס try...except ҅˸븇) ס , assertRaises ݵ 굎 Ђ. ݵ ˼ ס (roman.OutOfRangeError), ﹚(toRoman), toRoman˂ 빚(4000) 煫 , assertRaises ˂ toRoman ̉졒 ס roman.OutOfRangeError 騸 肄. (﹚ ւ ݵ ˼ ̹ һ ȡ ̅ ݱނ ˅?) | |
| , ˼ ˅. 즗, 0 ˸˂ ۹ , 翫 (testZero testNegative). testZero, toRoman 0 ̉ roman.OutOfRangeError ; ס roman.OutOfRangeError (ס ˂ ՠ졁һ ˼, ס ը), 煵. | |
| 禡 #3˼ toRoman -۹ ۂ, toRoman (0.5) ̉ roman.NotIntegerError . toRoman roman.NotIntegerError , 煵. |
˸˂ 禡˼, toRoman 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)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)
| Ғ ˼ ț ; ܁˼ toRoman һ 嵴 ȍ ܁졜 騂 . 廡 Ȃ 翫 һ Ȃ : roman.InvalidRomanNumeralError. ס˼ (roman.OutOfRangeError roman.NotIntegerError ) roman.py ˂ ˅ ̄ ˂ ̋ . ̋ ˂ , ˌ˂ ՠ . roman.py ӱ . |
, ˼ ˤ˂ , ﹚˂ , ȗ̉˞ ﹚˂ ւ졒 ˅ է , һ A B 졒 һ B A . , ˼ “ȡ (sanity check)” A B A, ˂ ܵ ՚ 桒, ՚ 桒, ˼ ˂ ՚ է́ 桒, ˅ .
禡 ࡢ
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):![]()
numeral = roman.toRoman(integer) result = roman.fromRoman(numeral) self.assertEqual(integer, result)
| ˟ range ﹚ ˅, һ ס˼ ˂ 빚 ̉, ס˼ ۹˂ ՠ嵴 տ 빚 (1) ¹˞ տ 빚(4000) һ ւ 桒 . , 1..3999, ס˼ 챉 ˤ ՟ˤ. | |
| ȡ ݱނ졒 ˼ (빚) ҄煱 integer(۹) 즗 ; ס˼ ꡜ 坡 . | |
| ˞ Ғ ֹ˞ 豉 : һ˂ (integer) ̑, ס (numeral) , ס (result) 졒 ˸ ˼ ҵ 낄. , assertEqual 畸 煵 . ݵ , assertEqual ȗ ղ , ˟̹ testSanity ղ , . |
˂ 禡˼ 굎 Ҁ ס굎˼ ˂˞ ȍ챉 ը:
ȍ˼, ס굎˼ ˼ ˂˞. , fromRoman ˼ ը ը ۂ. һ ס굎˼ ˟ ˂˞ ˼ ; toRoman ȗ ը˂ ̉ ՠ, fromRoman˼ ˞ ը˂ , ˂ “ȡ (sanity check)” (禡 #6)˼ ܂ . 'ס˼ (only) ը˂ ' ȍ˼ ˂˞, һ ݵ ̸ 쵒, ը ȗ ըϡ, ˤ ˟ ۂ ˅. ס ۂ ˅, ˅
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())
| ˌ ˼ ס ݵ . ס˼ toRoman ՠ ˼ ˼ 皲 졟 ˅ ; ը˼ ˂ ˂ 翫. ը- ˟ 翫. ˼ , ˟̹ ՟ˤ˂ 졒 toRoman ̉븇, ȡ (sanity check) ͂졒 ˼ 皵 .[11] һ ס˼ ˞ ˤՠ : ˂ ը . ȡ 衜 ͂졒, ܂ ȗȗ . ˼ ˼ ܹ ˂ ըϡ Dz ۂ嵴 ܂ ± . ˂ ܹ ס굎 Dz ± , ס˼ ˧-낧 騸 . | |
| Տ 炄 ˅: toRoman ȗ ը ՠ “ 衒 ˅˸” 졒, ˞ ס˂ ՠ ը fromRoman ը . ? Ҁ 'toRoman ȗ ը ՠ '˼ ˞ 禡 ը. , ס ȗ ը ՠ쵵 禡 , testToRomanCase , һ ˟ . ˼ ˂ ˞ : ݵ ꡜ ˅ . ݵ ҵ . | |
| fromRoman˂ ՠ 즗. ˼ ˞碂 ը; ﹚ ՠ 졒 ǵ , ˼ ՠ ՚. , ס . ՠ ǡ굵 ; ס˼ fromRoman ը . |
˂ 칼Ղ, ˂ 챉 ̵졒 ˅ 챉 ̡. 硒 , ݵ ܂ ˅ roman.py˂ Վ һ һ ס굎 ˅.
, ˼ ꡜ ̴ ȍ ϵ ˅ (Windows, UNIX, Mac OS).
"""Convert to and from Roman numerals""" #Define exceptions class RomanError(Exception): passclass OutOfRangeError(RomanError): pass
class NotIntegerError(RomanError): pass class InvalidRomanNumeralError(RomanError): pass
def toRoman(n): """convert integer to Roman numeral""" pass
def fromRoman(s): """convert Roman numeral to integer""" pass
| ˂ ̋ ˂ վ. , ˼ ˍ 븇 ˂ . Exception (湚˞ ˼ ) 챉 ˌ, ס˼ ݵ ˌ ȗ . һ (Exception ȗ) RomanError ˂嵴, ס˼ һ˂ ݵ ̋ . ˼ ˂ ը; һ Exception ˞ Ҽ˞ ȗ ˅. | |
| OutOfRangeError NotIntegerError toRoman ˂ ȍ, ToRomanBadInput ۵ , ˂ 飂 . | |
| InvalidRomanNumeralError fromRoman ˂ ȍ稹, FromRomanBadInput ۵ , 飂 . | |
| , ˂ ﹚ ˤ API 챉 , һ ס굎 챉 皫 , ˂ ղ pass ȍ ס굎 . |
˞ ( ̀煹 ~): ˂ ˞ ˼ ݵ 硒 . , ݵ ܂ . ȍ, 1 , romantest.py ղ 졒 ǡ굵-皲 ﹚ 皡 ۵ ˍ .
romantest1.py -v ჲ- ȍ 즗, ס˼ ̉ 騂 Dz 翂 ˅ ˅. , ˂ ̉˼ ꡜ 炯 :
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---------------------------------------------------------------------- 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
---------------------------------------------------------------------- Ran 12 tests in 0.040s
FAILED (failures=10, errors=2)
roman ݵ˂ 篼 Ղ, 졒 ҄ ̡.
, ˼ ꡜ ̴ ȍ ϵ ˅ (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""" result = "" for numeral, integer in romanNumeralMap: while n >= integer:
result += numeral n -= integer return result def fromRoman(s): """convert Roman numeral to integer""" pass
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 ... okfromRoman 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
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
| toRoman˼, ȍ, ȗ ը ՠ, Ҁ ˂ romanNumeralMap ը ˂챉 ը. һ . | |
| ˅: toRoman ﹚˂ ՚˟˼ . 즗, ס˼ ֡˞皫 , һ ס˼ ˼ 皡, ﹚˂ . ւ﵂ ˼ -ը˂ ݵ Ȑ̉ 嵎, ˌ (3999), ˌ (3888) Ȑ̉ . , ﹚ ҅ ˅ ˼ 塻 Ғ˞ 騸 ˅. | |
| ﹚ һ “” ; ס˼ ݵ Ҽ˞ һ ܂. ס˼ , Ҁ һ 뵵 ւ ը. (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)
toRoman (1 3999˂ ۹˂) ˼ 騂 Ղ, ס ( ݵ ) һ 塻뵵 騂 쵵 ̡.
, ˼ ꡜ ̴ ȍ ϵ ˅ (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):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 def fromRoman(s): """convert Roman numeral to integer""" pass
| ˼ ˅ : տ . ˼ 'if not ((0 < n) and (n < 4000))' , һ ס ܱ . ˼ ˂ ՟ˤ , ס˼ , ˸, 0 塻 һւ . | |
| ˼ raise йը 皡 ӫ. ˼ ˌ ˅ ˂ ̋ ˅. տ Ҽ, 皫, ˞; 煲翫, ̉嵂 ̧˞ ס˼ ̉嵃 . | |
| ˼ ˂ . . | |
| ﹚˂ һ皫 . |
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 ... okfromRoman(toRoman(n))==n for all n ... FAIL 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
| toRoman˼ ˟ 嵴, ס˼ 疡 . 2 ݵ ˟ , ˂ ǡ굵 . | |
| һ ˼ ˂ ݵ һ . , testDecimal˼ int(n) <> n˂ ը . toRoman ҄ , int(n) <> n ס 貮ۡ NotIntegerError 嵴, ס testDecimal ˅ . | |
| , testNegative not (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)
| 6 ˂ 킄, ݵ fromRoman ¡: , ˂ Ҽ˞ һ , ը , ȡ . ס˼ toRoman ˅ ݵ ˂킄. (ס˼ ȡ 衜 ¡, һ ס˼ fromRoman , ס˼ .) ס˼ 皱 toRoman 챉 ̧ ˂킄. ӱ, , “ ” ̧˞ 赵 ݵ 皂즗. 皂즗. 皱. Ҳ稦. |
| ֡˞ ˅ ˌ ˼ ̧. ﹚ ˤ ݵ , ﹚ 皂즗. ˟̹ ݵ ݵ , ݵ 皂즗. | |
toRoman 칼Ղ, fromRoman ̡. Ҽ˞ ۹ 煫 ˂ Ҽ낄 , ˼ toRoman ﹚ 坡 .
, ˼ ꡜ ̴ ȍ ϵ ˅ (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:result += integer index += len(numeral) return result
| ˂ ܁˼ 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 ... oktoRoman 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 ˼ , ˞ , . | |
| 填 ˂ ȡ (sanity check) . ͂, toRoman fromRoman , ݵ ˼ ˞ Ғ˞ 騸 ˅. ( ˌ皫 ; ˞ ˼ 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)
fromRoman ˼ ˞ Ղ, ˂ 禡 ̧ ҅ ̡: һ ס ˞ 쵵 . ס˼ ը վ ̣ ˂ ס ۂ վ ̣ ˂킄. ˼ toRoman ˞ ᮫, һ ˸ ȍ ˅ 傄 ˅: ۱ .
۱ ւ 졒 ۱ 101 , 皱 ˼ .
ˌ˂ ՠ , һ ˂ ˅. տ填 ̵ˤ , ˅, ˂ M ը ˂ .
Example 5.18. Checking for thousands
>>> import re >>> pattern = '^M?M?M?$'>>> re.search(pattern, 'M')
<SRE_Match object at 0106FB58> >>> re.search(pattern, 'MM')
<SRE_Match object at 0106C290> >>> re.search(pattern, 'MMM')
<SRE_Match object at 0106AA38> >>> re.search(pattern, 'MMMM')
>>> re.search(pattern, '')
<SRE_Match object at 0106F4A8>
Վ˂ ̵˂ ᮫, Ҁ, , ȗ Տ˞ ˅ վൎ ˅ ը.
˂ ܁ ˅:
˂ ܁˼ 禂͵ ˅:
Example 5.19. Checking for hundreds
>>> import re >>> pattern = '^M?M?M?(CM|CD|D?C?C?C?)$'>>> re.search(pattern, 'MCM')
<SRE_Match object at 01070390> >>> re.search(pattern, 'MD')
<SRE_Match object at 01073A50> >>> re.search(pattern, 'MMMCCC')
<SRE_Match object at 010748A8> >>> re.search(pattern, 'MCMC')
>>> re.search(pattern, '')
<SRE_Match object at 01071D98>
! ۱ һ ˅ ? Վ˂ ̵˂ ፲ . ( ˌ˂ ՠ, ۱ ը , ˉ챉 , ˞ ס˼ ˂ - ը .) ﵵ, ݵ , ˂ ˂ , Ҁ ס굎˼ ˼ ܁ ը.
, ˼ ꡜ ̴ ȍ ϵ ˅ (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?)$'def fromRoman(s): """convert Roman numeral to integer""" 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
| ˼ , ̵˂ Վ˂ 쫿 ܁˂ ¹. ˂ XC (90), XL (40)һ , ˼ ˞ L ˸ 0 3ұ˂ ˞ X ը . ˂ IX (9), IV (4)һ, ˼ ˞ V ˸ 0 3ұ˂ ˞ I ը . | |
| ݵ Ғ ˂ ۱ ҅Ղ, ȍ . re.search ̹ ՠ, ۱ ˼ 졒 ˂ ˼ ; , ˂ ˼ . |
, ొ ۱ ݵ ˂ һւ ˅ ˼ ˂ . һ ݫ , ȓ :
Example 5.21. Output of romantest5.py against roman5.py
fromRoman should only accept uppercase input ... oktoRoman should always return uppercase ... 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 12 tests in 2.864s OK
| ˂ ݵ , 皂즗. | |
̅ ֡˞ 硒 ˸ 졒, ՚ 첔Ы. һ “bug” Dz ˂? ՚ ֱ ˞ .
>>> import roman5 >>> roman5.fromRoman("")0
| ? ˟˂ ը 챉 ˤ ۱ . , ˼ ˼ ۱ ˂ ̅ ՚˟ ˟ . ס˼ ՚; ¹˞ ը 坡 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, "")![]()
|
|
ˍᇡ ˅. fromRoman ը ̉졒 ס InvalidRomanNumeralError |