将整数转换为36进制

8

strtoi(x,base=36)可以将一个基于36进制编码的字符串转换成整数:

strtoi("zzzz",base=36)
[1] 1679615

是否有一种函数可以实现这个操作的逆运算,即给定一个正整数,返回其对应的36进制数?本质上,我正在寻找一个itostr()函数,使得:

itostr(1679615,base=36)
[1] "zzzz"

我不需要36以外的任何进制,但是如果有一个base参数会很好。


同时,https://github.com/statsmaths/baseN - Ben Bolker
这不是重复的问题,但类似的问题在这里讨论过。 - RHertel
3个回答

7

我相信如果你安装了BBmisc包,它将提供itostr函数。

library(BBmisc)
itostr(1679615,base=36)
[1] "zzzz"

5

我不知道是否有任何实现,但这个算法并不难。以下是适用于32位有符号整数的算法。

intToBase36 <- function(int) {
  stopifnot(is.integer(int) || int < 0)

  base36 <- c(as.character(0:9),LETTERS)
  result <- character(6)
  i <- 1L
  while (int > 0) {
    result[i] <- base36[int %% 36L + 1L]
    i <- i + 1L
    int <- int %/% 36L
  }
  return(paste(result, sep="", collapse=""))
}

如果需要支持更大的整数,您可以使用 bit64Rmpfr 软件包。


不错。我有点惊讶它在 intToBase36(1679615) 处崩溃了,但是当然 is.integer(1679615)FALSE,稍微使用 intToBase36(1679615L) 进行强制转换就可以解决问题了。 - Stephan Kolassa

4
快速的 Rcpp 技巧是:这个链接
library(inline)

cxxfunction(signature(x="numeric"), body='
unsigned int val = as<unsigned int>(x);
static char const base36[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::string result;
result.reserve(14);
do {
  result = base36[val % 36] + result;
} while (val /= 36);
return wrap(result);
', plugin="Rcpp") -> base36enc

base36enc(36)
## [1] "10"

base36enc(72)
## [1] "20"

base36enc(73)
## [1] "21"

虽然这段代码可以使用,但在生产环境中还需要添加更多代码。

另一个答案提到的BBmisc包也是基于C语言的,因此它可能是一个良好且高效的选择。


#谢谢,Joshua。我不知道怎么发生的(而且我应该注意到了)。 - hrbrmstr
这看起来很有趣,但说实话,对于我这个非Rcpp用户来说有点令人生畏。(我猜想经典的回答是我应该成为一个Rcpp用户。我承认我缺乏时间。)此外,我遇到了一些神秘的错误,可能与我的德语默认区域设置有关:“include/Rcpp/Date.h:103: error: field 'm_tm' has incomplete type”。 - Stephan Kolassa

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