ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Decimal to Roman numerals
Submitter: Victor Yang (other recipes)Victor Yang (other recipes)
Last Updated: 2005/05/27
Version no: 1.0
Category: Algorithms

 

Not Rated yet


Description:

Convert decimals to Roman numerials.
I use a recursive algorithm here since it reflects the thinking clearly in code.
A non-recursive algothrithm can be done as well.

Source: Text Source

"""
Victor Yang, pythonrocks@yahoo.com

Convert decimals to Roman numerials.
I use a recursive algorithm here since it reflects the thinking clearly in code.
A non-recursive algothrithm can be done as well.

usage: python roman.py 
It will run the test case against toRoman function
"""

import sys
import unittest


# these two lists serves as building blocks to construt any number
# just like coin denominations.
# 1000->"M", 900->"CM", 500->"D"...keep on going 
decimalDens=[1000,900,500,400,100,90,50,40,10,9,5,4,1]
romanDens=["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]


def toRoman(dec):
	"""
	Perform sanity check on decimal and throws exceptions when necessary
	"""		
        if dec <=0:
	  raise ValueError, "It must be a positive"
         # to avoid MMMM
	elif dec>=4000:  
	  raise ValueError, "It must be lower than MMMM(4000)"
  
	return decToRoman(dec,"",decimalDens,romanDens)

def decToRoman(num,s,decs,romans):
	"""
	  convert a Decimal number to Roman numeral recursively
	  num: the decimal number
	  s: the roman numerial string
	  decs: current list of decimal denomination
	  romans: current list of roman denomination
	"""
	if decs:
	  if (num < decs[0]):
	    # deal with the rest denomination
	    return decToRoman(num,s,decs[1:],romans[1:])		  
	  else:
	    # deduce this denomation till num<desc[0]
	    return decToRoman(num-decs[0],s+romans[0],decs,romans)	  
	else:
	  # we run out of denomination, we are done 
	  return s


class DecToRomanTest(unittest.TestCase):

	def setUp(self):
		print '\nset up'
	def tearDown(self):
		print 'tear down'
	
	def testDens(self):
		
	   for i in range(len(decimalDens)):
		r=toRoman(decimalDens[i])
		self.assertEqual(r,romanDens[i])

	def testSmallest(self):
		self.assertEqual('I',toRoman(1))

	def testBiggest(self):
		self.assertEqual('MMMCMXCIX',toRoman(3999))

	def testZero(self):
		self.assertRaises(ValueError,toRoman,0)

	def testNegative(self):
		
		self.assertRaises(ValueError,toRoman,-100)


	def testMillonDollar(self):
		
		self.assertRaises(ValueError,toRoman,1000000)

		

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

Discussion:

Just for fun.



Add comment

Number of comments: 2

For grins: A non-recursive version, Raymond Hettinger, 2005/06/15

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

def decToRoman(num):
    if num <= 0 or num >= 4000 or int(num) != num:
        raise ValueError('Input should be an integer between 1 and 3999')
    result = []
    for d, r in coding:
        while num >= d:
            result.append(r)
            num -= d
    return ''.join(result)


for i in xrange(1,4000):
    print i, decToRoman(i)

Add comment

Now it's Online, greg p, 2007/08/05
I made this recipe into an online utility. Check it out:
http://www.utilitymill.com/utility/Decimal_to_Roman_Numerals
Add comment



Highest rated recipes:

1. A simple XML-RPC server

2. Web service accessible ...

3. IPy Notify

4. Changing return value ...

5. Quantum Superposition

6. Pickle objects under ...

7. Generalized delegates ...

8. Reorder a sequence (uses ...

9. Setting Win32 System ...

10. ObjectMerger




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.