在R中将罗马数字转换为阿拉伯数字

32
在R中,有一个非常好的函数as.roman在基础设置中:
as.roman(79)
# [1] LXXIX

是否有一种反函数可以将罗马数字转换为阿拉伯数字?

(我知道我可以自己编写,但我更喜欢使用已经准备好或最好是标准的函数,不幸的是找不到一个。标准库或包函数是首选解决方案)

3个回答

44

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

12

as.roman代码中,您可以找到.roman2numeric函数,并且如果运行getAnywhere(".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
}
您可以访问 .roman2numeric,按照@rawr在他/她的评论中的建议将罗马数字转换为十进制数。
> utils:::.roman2numeric("III")
[1] 3
> utils:::.roman2numeric("XII")
[1] 12
> utils:::.roman2numeric("LXXIX")
[1] 79

7
根据文档,R中的罗马数字是"roman"类对象,内部表示为整数,并具有适当的打印、格式化、子集和强制转换为character的方法。因此,您应该能够使用as.integer()将整数值返回。
as.integer(as.roman(79)+as.roman(12))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接