/Doc/tools/roman.py
http://unladen-swallow.googlecode.com/ · Python · 80 lines · 67 code · 8 blank · 5 comment · 4 complexity · 9c65b77db9b9eaff722ff9383213fb86 MD5 · raw file
- """Convert to and from Roman numerals"""
- __author__ = "Mark Pilgrim (f8dy@diveintopython.org)"
- __version__ = "1.4"
- __date__ = "8 August 2001"
- __copyright__ = """Copyright (c) 2001 Mark Pilgrim
- This program is part of "Dive Into Python", a free Python tutorial for
- experienced programmers. Visit http://diveintopython.org/ for the
- latest version.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the Python 2.1.1 license, available at
- http://www.python.org/2.1.1/license.html
- """
- 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):
- 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 = 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)
- def fromRoman(s):
- """convert Roman numeral to integer"""
- if not s:
- raise InvalidRomanNumeralError, 'Input can not be blank'
- if not romanNumeralPattern.search(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