/ NumberRecipes / Cookbook.NumberRecipesRomanNumerals

You want to convert decimal numbers to Roman numerals and Roman numerals to decimal numbers.

; decimal->roman : integer -> string ; format the integer num using roman numerals (define (decimal->roman num) (let ((decimal-numbers (list 1000 900 500 400 100 90 50 40 10 9 5 4 1)) (roman-numbers (list "M" "CM" "D" "CD" "C" "XC" "L" "XL" "X" "IX" "V" "IV" "I"))) (decimal->roman-aux num "" decimal-numbers roman-numbers))) ; decimal->roman-aux : integer string (list number) (list string) -> string ; append the numbers num formatted as roman numerals to the string s, ; using the roman numerals in roman-numbers with corresponding ; decimal values in decimal-values (define (decimal->roman-aux num s decimal-numbers roman-numbers) (if (null? decimal-numbers) s (if (>= num (car decimal-numbers)) (decimal->roman-aux (- num (car decimal-numbers)) (string-append s (car roman-numbers)) decimal-numbers roman-numbers) (decimal->roman-aux num s (cdr decimal-numbers) (cdr roman-numbers)))))

The solution for the convertion between Roman numerals and decimal numbers is shown in the next code.

(require (lib "13.ss" "srfi")) (read-case-sensitive #t) ; due to the case expression ; roman->decimal : string -> integer ; convert a string with (uppercase) roman numerals to an integer (define (roman->decimal s) (cond [(string= s "") 0] [(= (string-length s) 1) (case (string->symbol s) [(I) 1] [(V) 5] [(X) 10] [(L) 50] [(C) 100] [(D) 500] [(M) 1000] [else 0])] [else (+ (roman->dec (string-drop s 2)) (case (string->symbol (substring/shared s 0 2)) [(IV) 4] [(IX) 9] [(XL) 40] [(XC) 90] [(CD) 400] [(CM) 900] [else (+ (roman->dec (substring/shared s 0 1)) (roman->dec (string-drop s 1)))]))]))

If the list `decimal-numbers`

is empty we just return the string.

If the number is greater or equal than the first element of the decimals list we need to make a recursive call of this procedure but with the first argument as the rest between the number and the first element of the decimals list, and as a second argument an string that contains that we had and the first element of the roman numeral list and the other two arguments are the decimal and roman lists without changes.

If the number is less than the first element of the decimal list we just only make a recursive call with the number and the string unchanged and the decimal and roman lists without their first element. In the second code we use the srfi 13 that defines many procedures to manipulate strings, in other case it could be very difficult to resolve.

The main idea of the algorithm is recognize between two cases:

If the first character of the string is a simple symbol (I,V,X,L,C,D,M).

If the two first characters of the string are a double symbol (IV, IX, XL, XC, CD, CM).

Then we just sum the decimal values of the symbol that we have recognized.

-- EmiliaBarajas - 18 May 2004

CookbookForm | |
---|---|

TopicType: | Recipe |

ParentTopic: | NumberRecipes |

Next Topic: | NumberRecipeRandomNumber |

The copyright for certain compilations of material taken from this website is held by the SchematicsEditorsGroup - see ContributorAgreement & LGPL.

Other than such compilations, this material can be redistributed and/or modified under the terms of the GNU Lesser General Public License (LGPL), version 2.1, as published by the Free Software Foundation.

Ideas, requests, problems regarding Schematics Cookbook? Send feedback. / You are Main.guest