如何在 R 中的数字系统之间进行转换?
How can I convert between numeral systems in R?
我看到有一个内置函数用于...相当抽象...使用从十进制表示形式转换为罗马数字 (Convert roman numerals to numbers in R),但我不能找到一种从十进制转换为其他类似系统的内置方法,例如 base 3 或 base 11。我看到二进制和十六进制(base 16)得到很好的支持,但是是否有用于转换 to/from 任意位置数字系统。
我可以制作这样一个包,但我怀疑它已经存在并且我的 google-fu 只是不够用?
您可以编写自己的 S3 class:
base <- function(b, base = 10)
{
base <- as.integer(base)
if(base > 36 | base < 2) stop("'base' must be between 2 and 36.")
structure(lapply(b, function(x)
{
n <- ceiling(log(x, base))
vec <- numeric()
val <- x
while(n >= 0)
{
rem <- val %/% base^n
val <- val - rem * base^n
vec <- c(vec, rem)
n <- n - 1
}
while(vec[1] == 0 & length(vec) > 1) vec <- vec[-1]
structure(x, base = base, representation = vec)
}), class = "base")
}
需要 format
和 print
方法:
format.base <- function(b, ...)
{
sapply(b, function(x)
{
glyphs <- c(0:9, LETTERS)
base <- attr(x, "base")
vec <- attr(x, "representation")
paste0(glyphs[vec + 1], collapse = "")
})
}
print.base <- function(b, ...) print(format(b), quote = FALSE)
我们还需要确保数学运算正常进行:
Ops.base <- function(e1, e2) {
base <- attr(e1[[1]], "base")
e1 <- unlist(e1)
e2 <- unlist(e2)
base(NextMethod(.Generic), base)
}
Math.base <- function(e1, e2) {
base <- attr(e1[[1]], "base")
e1 <- unlist(e1)
e2 <- unlist(e2)
base(NextMethod(.Generic), base)
}
如果您想在数据框中使用它,您需要一个 as.data.frame
方法:
as.data.frame.base <- function(b, ...)
{
structure(list(b),
class = "data.frame",
row.names = seq_along(b))
}
哪些都允许以下行为:
data.frame(binary = base(1:20, 2), hex = base(1:20, 16), oct = base(1:20, 8))
#> binary hex oct
#> 1 1 1 1
#> 2 10 2 2
#> 3 11 3 3
#> 4 100 4 4
#> 5 101 5 5
#> 6 110 6 6
#> 7 111 7 7
#> 8 1000 8 10
#> 9 1001 9 11
#> 10 1010 A 12
#> 11 1011 B 13
#> 12 1100 C 14
#> 13 1101 D 15
#> 14 1110 E 16
#> 15 1111 F 17
#> 16 10000 10 20
#> 17 10001 11 21
#> 18 10010 12 22
#> 19 10011 13 23
#> 20 10100 14 24
并且:
x <- base(67, 11)
y <- base(35, 2)
x + y
#> [1] 93
base(x + y, 10)
#> [1] 102
我看到有一个内置函数用于...相当抽象...使用从十进制表示形式转换为罗马数字 (Convert roman numerals to numbers in R),但我不能找到一种从十进制转换为其他类似系统的内置方法,例如 base 3 或 base 11。我看到二进制和十六进制(base 16)得到很好的支持,但是是否有用于转换 to/from 任意位置数字系统。
我可以制作这样一个包,但我怀疑它已经存在并且我的 google-fu 只是不够用?
您可以编写自己的 S3 class:
base <- function(b, base = 10)
{
base <- as.integer(base)
if(base > 36 | base < 2) stop("'base' must be between 2 and 36.")
structure(lapply(b, function(x)
{
n <- ceiling(log(x, base))
vec <- numeric()
val <- x
while(n >= 0)
{
rem <- val %/% base^n
val <- val - rem * base^n
vec <- c(vec, rem)
n <- n - 1
}
while(vec[1] == 0 & length(vec) > 1) vec <- vec[-1]
structure(x, base = base, representation = vec)
}), class = "base")
}
需要 format
和 print
方法:
format.base <- function(b, ...)
{
sapply(b, function(x)
{
glyphs <- c(0:9, LETTERS)
base <- attr(x, "base")
vec <- attr(x, "representation")
paste0(glyphs[vec + 1], collapse = "")
})
}
print.base <- function(b, ...) print(format(b), quote = FALSE)
我们还需要确保数学运算正常进行:
Ops.base <- function(e1, e2) {
base <- attr(e1[[1]], "base")
e1 <- unlist(e1)
e2 <- unlist(e2)
base(NextMethod(.Generic), base)
}
Math.base <- function(e1, e2) {
base <- attr(e1[[1]], "base")
e1 <- unlist(e1)
e2 <- unlist(e2)
base(NextMethod(.Generic), base)
}
如果您想在数据框中使用它,您需要一个 as.data.frame
方法:
as.data.frame.base <- function(b, ...)
{
structure(list(b),
class = "data.frame",
row.names = seq_along(b))
}
哪些都允许以下行为:
data.frame(binary = base(1:20, 2), hex = base(1:20, 16), oct = base(1:20, 8))
#> binary hex oct
#> 1 1 1 1
#> 2 10 2 2
#> 3 11 3 3
#> 4 100 4 4
#> 5 101 5 5
#> 6 110 6 6
#> 7 111 7 7
#> 8 1000 8 10
#> 9 1001 9 11
#> 10 1010 A 12
#> 11 1011 B 13
#> 12 1100 C 14
#> 13 1101 D 15
#> 14 1110 E 16
#> 15 1111 F 17
#> 16 10000 10 20
#> 17 10001 11 21
#> 18 10010 12 22
#> 19 10011 13 23
#> 20 10100 14 24
并且:
x <- base(67, 11)
y <- base(35, 2)
x + y
#> [1] 93
base(x + y, 10)
#> [1] 102