You are previewing Ruby Cookbook.
by Lucas Carlson... Published by O'Reilly Media, Inc.

# 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? ...```