Sander Ehmsen
Sander Ehmsen

Reputation: 83

How to transform large numbers to roman in R

I want to transform large numbers (below 10.000) to roman. I know the as.roman function. But that does only go to 3899.

Is it possible to change in the source code in this function and force it to transform the larger numbers - or is it possible to write a new function?

I am running R 3.3.0.

Best, Sander.

Upvotes: 1

Views: 222

Answers (1)

bgoldst
bgoldst

Reputation: 35324

A while back I wrote an integer-to-Roman conversion function in Perl. I just rewrote it in R for this answer. Note that I use the newfangled strrep() function which I believe was only added in 3.3.0.

integerToRoman <- function(x) {

    x <- as.integer(x);

    neg <- x<0L;
    x <- abs(x);

    cnt <- integer(length(x));
    res <- rep('',length(x));
    if (any(m <- x==0L)) { res[m] <- 'nulla'; };
    if (any(m <- x>=1000L)) { cnt[m] <- x[m]%/%1000L; x[m] <- x[m]%%1000L; res[m] <- strrep('M',cnt[m]); };
    if (any(m <- x>=900L)) { res[m] <- paste0(res[m],'CM'); x[m] <- x[m]-900L; };
    if (any(m <- x>=500L)) { res[m] <- paste0(res[m],'D'); x[m] <- x[m]-500L; };
    if (any(m <- x>=400L)) { res[m] <- paste0(res[m],'CD'); x[m] <- x[m]-400L; };
    if (any(m <- x>=100L)) { cnt[m] <- x[m]%/%100L; x[m] <- x[m]%%100L; res[m] <- paste0(res[m],strrep('C',cnt[m])); };
    if (any(m <- x>=90L)) { res[m] <- paste0(res[m],'XC'); x[m] <- x[m]-90L; };
    if (any(m <- x>=50L)) { res[m] <- paste0(res[m],'L'); x[m] <- x[m]-50L; };
    if (any(m <- x>=40L)) { res[m] <- paste0(res[m],'XL'); x[m] <- x[m]-40L; };
    if (any(m <- x>=10L)) { cnt[m] <- x[m]%/%10L; x[m] <- x[m]%%10L; res[m] <- paste0(res[m],strrep('X',cnt[m])); };
    if (any(m <- x>=9L)) { res[m] <- paste0(res[m],'IX'); x[m] <- x[m]-9L; };
    if (any(m <- x>=5L)) { res[m] <- paste0(res[m],'V'); x[m] <- x[m]-5L; };
    if (any(m <- x>=4L)) { res[m] <- paste0(res[m],'IV'); x[m] <- x[m]-4L; };
    if (any(m <- x>=1L)) res[m] <- paste0(res[m],strrep('I',x[m]));

    if (any(neg)) res[neg] <- paste0('-',res[neg]);

    res;

}; ## end integerToRoman()

Demo:

set.seed(319072L); data.frame(int=x <- sample(seq(0L,5e3L),20L),roman=integerToRoman(x));
##     int          roman
## 1   614          DCXIV
## 2  4825    MMMMDCCCXXV
## 3     6             VI
## 4  4721     MMMMDCCXXI
## 5     9             IX
## 6  3333   MMMCCCXXXIII
## 7  2114         MMCXIV
## 8  4861    MMMMDCCCLXI
## 9  1042          MXLII
## 10 3609        MMMDCIX
## 11  417         CDXVII
## 12  241          CCXLI
## 13    3            III
## 14 4952      MMMMCMLII
## 15 1370        MCCCLXX
## 16 1789     MDCCLXXXIX
## 17 3730      MMMDCCXXX
## 18 2275       MMCCLXXV
## 19 1139        MCXXXIX
## 20 4898 MMMMDCCCXCVIII

Upvotes: 4

Related Questions