2014-01-14 70 views
17

在R,有一个很大的功能as.roman在非常基础的设置:转换罗马数字编号中的R

as.roman(79) 
# [1] LXXIX 

是否有将罗马数字转换为数字的反函数?

(我知道可以写自己,但我更喜欢使用已经制备的或优选标准功能,可惜的不能找到一个,标准库或包函数是首选溶液)

回答

28

as.roman()返回的一个目的类roman,所以R认识到这一点。您可以直接将其重新转换为as.numeric()的阿拉伯数字。如果你有一个符合条件的字符串,它可以是一个有效的罗马数字,你可以强制它与as.roman()的罗马类对象,然后通过组合强制函数将它强制为阿拉伯数字。考虑:

> 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 
6

roman号码R的,根据the docs"roman"类的

对象,其在内部表示为整数,并具有适用于印刷的方法,格式化,子集,和胁迫到character

因此,你应该能够得到的整数值回用as.integer():如果您运行getAnywhere(".roman2numeric")

代码

as.integer(as.roman(79)+as.roman(12)) 
10

as.roman代码,你可以找到.roman2numeric和它的代码可以看出是:

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 
} 

你c访问.roman2numeric,并按@rawr在他/她的评论中建议的方式将罗马数字转换为十进制数字。

> utils:::.roman2numeric("III") 
[1] 3 
> utils:::.roman2numeric("XII") 
[1] 12 
> utils:::.roman2numeric("LXXIX") 
[1] 79