Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert roman numerals to numbers in R

Tags:

In R, there is a great function as.roman in the very base setup:

as.roman(79) # [1] LXXIX 

Is there an inverse function that would convert roman numerals to numbers?

(I know I can write it myself but I prefer to use already prepared or preferably standard functions, unfortunatelly cannot find one. Standard library or package function is a prefered solution)

like image 393
Tomas Avatar asked Jan 14 '14 15:01

Tomas


People also ask

How do you find Roman numeral numbers?

To learn Roman numerals, know that I = 1, V = 5, X = 10, L = 50, C = 100, D = 500, and M = 1,000. If a symbol comes after another symbol, then you add it to the symbol before it. For example, VI = 6 since V = 5 and I = 1. If a symbol comes before another symbol, subtract it instead.


2 Answers

as.roman() returns an object of class roman, so R recognizes it as such. You can directly turn it back into an Arabic numeral with as.numeric(). If you have a string that meets the criteria such that it could be a valid roman numeral, you can coerce it to a class roman object with as.roman(), and then coerce it into an Arabic numeral by composing the coercion functions. Consider:

> as.roman(79) [1] LXXIX > x <- as.roman(79) > x [1] LXXIX > str(x) Class 'roman'  int 79 > as.roman("LXXIX") [1] LXXIX > as.numeric(as.roman("LXXIX")) [1] 79 
like image 72
gung - Reinstate Monica Avatar answered Sep 19 '22 07:09

gung - Reinstate Monica


From as.roman code you can find .roman2numeric and its code can be seen if you run getAnywhere(".roman2numeric")

The code is:

function (x)  {   romans <- c("M", "CM", "D", "CD", "C", "XC", "L", "XL", "X",                "IX", "V", "IV", "I")   numbers <- c(1000L, 900L, 500L, 400L, 100L, 90L, 50L, 40L,                 10L, 9L, 5L, 4L, 1L)   out <- integer(length(x))   ind <- is.na(x)   out[ind] <- NA   if (any(!ind)) {     y <- toupper(x[!ind])     y <- gsub("CM", "DCCCC", y)     y <- gsub("CD", "CCCC", y)     y <- gsub("XC", "LXXXX", y)     y <- gsub("XL", "XXXX", y)     y <- gsub("IX", "VIIII", y)     y <- gsub("IV", "IIII", y)     ok <- grepl("^M{,3}D?C{,4}L?X{,4}V?I{,4}$", y)     if (any(!ok)) {       warning(sprintf(ngettext(sum(!ok), "invalid roman numeral: %s",                                 "invalid roman numerals: %s"), paste(x[!ind][!ok],                                                                      collapse = " ")), domain = NA)       out[!ind][!ok] <- NA     }     if (any(ok))        out[!ind][ok] <- sapply(strsplit(y[ok], ""), function(z) as.integer(sum(numbers[match(z,                                                                                              romans)])))   }   out } 

You can access to .roman2numeric and convert roman number to decimal numbers the way @rawr suggested in his/her comment.

> utils:::.roman2numeric("III") [1] 3 > utils:::.roman2numeric("XII") [1] 12 > utils:::.roman2numeric("LXXIX") [1] 79 
like image 35
Jilber Urbina Avatar answered Sep 20 '22 07:09

Jilber Urbina