R:在不使用长度函数的情况下查找 bigz 向量的长度
R: Find length of bigz vector without using the length function
在R
中,要找到向量的长度(bigz
或不是),通常使用length
函数。例如
NonBigZ <- 1:10
NonBigZ
[1] 1 2 3 4 5 6 7 8 9 10
length(NonBigZ)
[1] 10
然而,使用 gmp
包,如果你声明一个 bigz
向量,向量的长度会自动返回。例如
BigZ <- as.bigz(1:10)
BigZ
Big Integer ('bigz') object of length 10: ## <<-- length given here
[1] 1 2 3 4 5 6 7 8 9 10
## This seems redundant as it is already given above
length(BigZ)
[1] 10
我想在不额外调用 length
的情况下检索该信息。我知道 length
快如闪电,但如果你能避免调用它,它可以节省相当多的时间。观察:
system.time(sapply(1:10^6, function(x) length(BigZ)))
user system elapsed
7.81 0.00 7.84
我试过 attributes(BigZ)
和 str(BigZ)
都无济于事。我也阅读了 gmp 文档,但找不到任何内容。
正如@alexis_laz 在评论中指出的那样,gmp::print.bigz
已经计算了长度,但没有return 以任何可用格式计算。我深入研究了 gmp
源代码,发现了这个:
print.bigz <- function(x, quote = FALSE, initLine = is.null(modulus(x)), ...)
{
if((n <- length(x)) > 0) {
if(initLine) {
cat("Big Integer ('bigz') ")
kind <- if(isM <- !is.null(nr <- attr(x, "nrow")))
sprintf("%d x %d matrix", nr, n/nr)
else if(n > 1) sprintf("object of length %d", n) else ""
cat(kind,":\n", sep="")
}
print(as.character(x), quote = quote, ...)
}
else
cat("bigz(0)\n")
invisible(x)
}
如您所见,它使用 cat
函数来 return 您的 bigz
对象。从 this question and this answer 中检索请求的信息是可能的,但是,它不如简单地调用 length
有效。下面是一个非常粗略的获取长度的函数。
BigZLength <- function(x) {
b <- capture.output(x)
a <- strsplit(b[1], split=" ")[[1]][7]
if (!is.na(a)) {as.integer(substr(a,1,nchar(a)-1))} else {1L}
}
system.time(sapply(1:10^5, function(x) length(BigZ)))
user system elapsed
0.67 0.00 0.67
system.time(sapply(1:10^5, function(x) BigZLength(BigZ)))
user system elapsed
24.57 0.01 24.71
我相信您可以使用正则表达式(或其他东西)编写更高效的函数,但是,我认为它不会像简单地调用 length
那样高效。事实上,在上面的代码中,简单地获取 cat
的输出花费了大部分时间。
system.time(sapply(1:10^5, function(x) capture.output(BigZ)))
user system elapsed
20.00 0.00 20.03
上面关于获取源代码的说明
如果您熟悉 R
,您就会知道您可以通过简单地在控制台中键入函数并像这样打印它来查看给定函数的源代码:
numbers::nextPrime
function (n)
{
if (n <= 1)
n <- 1
else n <- floor(n)
n <- n + 1
d1 <- max(3, round(log(n)))
P <- Primes(n, n + d1)
while (length(P) == 0) {
n <- n + d1 + 1
P <- Primes(n, n + d1)
}
return(as.numeric(min(P)))
}
<environment: namespace:numbers>
然而,有时这是不可能的。例如 gmp::print.bigz
我们得到:
gmp::print.bigz
Error: 'print.bigz' is not an exported object from 'namespace:gmp'
进入 Joshua Ulrich 的精彩 question and answer。使用他在下面建议的代码,您可以下载任何包的源代码并在一行中解压。
untar(download.packages(pkgs = "gmp",
destdir = ".",
type = "source")[,2])
这会在您的目录中创建一个包含所有已编译代码的文件夹。上面的源代码是在.\gmp\R\biginteger.R
文件中找到的。
在R
中,要找到向量的长度(bigz
或不是),通常使用length
函数。例如
NonBigZ <- 1:10
NonBigZ
[1] 1 2 3 4 5 6 7 8 9 10
length(NonBigZ)
[1] 10
然而,使用 gmp
包,如果你声明一个 bigz
向量,向量的长度会自动返回。例如
BigZ <- as.bigz(1:10)
BigZ
Big Integer ('bigz') object of length 10: ## <<-- length given here
[1] 1 2 3 4 5 6 7 8 9 10
## This seems redundant as it is already given above
length(BigZ)
[1] 10
我想在不额外调用 length
的情况下检索该信息。我知道 length
快如闪电,但如果你能避免调用它,它可以节省相当多的时间。观察:
system.time(sapply(1:10^6, function(x) length(BigZ)))
user system elapsed
7.81 0.00 7.84
我试过 attributes(BigZ)
和 str(BigZ)
都无济于事。我也阅读了 gmp 文档,但找不到任何内容。
正如@alexis_laz 在评论中指出的那样,gmp::print.bigz
已经计算了长度,但没有return 以任何可用格式计算。我深入研究了 gmp
源代码,发现了这个:
print.bigz <- function(x, quote = FALSE, initLine = is.null(modulus(x)), ...)
{
if((n <- length(x)) > 0) {
if(initLine) {
cat("Big Integer ('bigz') ")
kind <- if(isM <- !is.null(nr <- attr(x, "nrow")))
sprintf("%d x %d matrix", nr, n/nr)
else if(n > 1) sprintf("object of length %d", n) else ""
cat(kind,":\n", sep="")
}
print(as.character(x), quote = quote, ...)
}
else
cat("bigz(0)\n")
invisible(x)
}
如您所见,它使用 cat
函数来 return 您的 bigz
对象。从 this question and this answer 中检索请求的信息是可能的,但是,它不如简单地调用 length
有效。下面是一个非常粗略的获取长度的函数。
BigZLength <- function(x) {
b <- capture.output(x)
a <- strsplit(b[1], split=" ")[[1]][7]
if (!is.na(a)) {as.integer(substr(a,1,nchar(a)-1))} else {1L}
}
system.time(sapply(1:10^5, function(x) length(BigZ)))
user system elapsed
0.67 0.00 0.67
system.time(sapply(1:10^5, function(x) BigZLength(BigZ)))
user system elapsed
24.57 0.01 24.71
我相信您可以使用正则表达式(或其他东西)编写更高效的函数,但是,我认为它不会像简单地调用 length
那样高效。事实上,在上面的代码中,简单地获取 cat
的输出花费了大部分时间。
system.time(sapply(1:10^5, function(x) capture.output(BigZ)))
user system elapsed
20.00 0.00 20.03
上面关于获取源代码的说明
如果您熟悉 R
,您就会知道您可以通过简单地在控制台中键入函数并像这样打印它来查看给定函数的源代码:
numbers::nextPrime
function (n)
{
if (n <= 1)
n <- 1
else n <- floor(n)
n <- n + 1
d1 <- max(3, round(log(n)))
P <- Primes(n, n + d1)
while (length(P) == 0) {
n <- n + d1 + 1
P <- Primes(n, n + d1)
}
return(as.numeric(min(P)))
}
<environment: namespace:numbers>
然而,有时这是不可能的。例如 gmp::print.bigz
我们得到:
gmp::print.bigz
Error: 'print.bigz' is not an exported object from 'namespace:gmp'
进入 Joshua Ulrich 的精彩 question and answer。使用他在下面建议的代码,您可以下载任何包的源代码并在一行中解压。
untar(download.packages(pkgs = "gmp",
destdir = ".",
type = "source")[,2])
这会在您的目录中创建一个包含所有已编译代码的文件夹。上面的源代码是在.\gmp\R\biginteger.R
文件中找到的。