Convert roman numerals to numbers in R

后端 未结 3 2049
遥遥无期
遥遥无期 2020-12-03 17:22

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 wo

相关标签:
3条回答
  • 2020-12-03 17:22

    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
    
    0 讨论(0)
  • 2020-12-03 17:25

    The roman numbers in R are, according to the docs:

    objects of class "roman" which are internally represented as integers, and have suitable methods for printing, formatting, subsetting, and coercion to character.

    You should therefore be able to get the integer value back using as.integer():

    as.integer(as.roman(79)+as.roman(12))
    
    0 讨论(0)
  • 2020-12-03 17:28

    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
    
    0 讨论(0)
提交回复
热议问题