With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

No credit card required

2.14. Doing Math with Roman Numbers

Problem

You want to convert between Arabic and Roman numbers, or do arithmetic with Roman numbers and get Roman numbers as your result.

Solution

The simplest way to define a `Roman` class that acts like `Fixnum` is to have its instances delegate most of their method calls to a real `Fixnum` (as seen in the previous recipe, Recipe 2.13). First we'll implement a container for the `Fixnum` delegate, and methods to convert between Roman and Arabic numbers:

```	class Roman
# These arrays map all distinct substrings of Roman numbers
# to their Arabic equivalents, and vice versa.
@@roman_to_arabic = [['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]]
@@arabic_to_roman = @@roman_to_arabic.collect { |x| x.reverse }.reverse

# The Roman symbol for 5000 (a V with a bar over it) is not in
# ASCII nor Unicode, so we won't represent numbers larger than 3999.
MAX = 3999

def initialize(number)
if number.respond_to? :to_str
@value = Roman.to_arabic(number)
else
Roman.assert_within_range(number)
@value = number
end
end

# Raise an exception if a number is too large or small to be represented
# as a
Roman number.
def  Roman.assert_within_range(number) unless number.between?(1, MAX) msg = "#{number} can't be represented as a Roman number." raise RangeError.new(msg) end end #Find the Fixnum value of a string containing a Roman number. def Roman.to_arabic(s) value = s if s.respond_to? ...```

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

No credit card required