2016-06-28 58 views
0

R中,要找到向量的長度(不管是否爲bigz),通常使用length函數。例如。R:在不使用長度函數的情況下查找bigz向量的長度

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文檔,但找不到任何東西。

+1

'gmp ::: print.bigz',也可以用'gmp :::length.bigz'來計算'length'。看起來'length.bigz'不僅僅是一個像'length'這樣的屬性訪問函數 - 例如參見'ns = c(1,10,50,100,200,500,1e3,5e3,1e4);時間= sapply(ns,function(n){x = as.bigz(seq_len(n)); summary(microbenchmark(length(x),unit =「ms」))$ median});情節(ns,時間)'。我想,創建「bigz」時將「length」保存爲屬性可能是值得的。 –

+0

而不是把你的答案放到你的問題中(並且讓問題看起來沒有解決),你應該回答你自己的問題。 – Gregor

+0

@Gregor,因爲我不確定我的答案是否足夠徹底,所以對於張貼答案猶豫不決。任何人,我已經採納了你的建議。 –

回答

1

正如@alexis_laz在評論中指出的那樣,gmp::print.bigz已經計算了長度,但沒有以任何可用的格式返回它。我做了一些深入挖掘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函數返回你的bigz對象。從this questionthis 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' 

輸入約書亞Ulrich的真棒questionanswer。使用他在下面建議的代碼,可以下載任何包的源代碼並將其解壓到一行中。

untar(download.packages(pkgs = "gmp", 
         destdir = ".", 
         type = "source")[,2]) 

這會在您的目錄中創建一個包含所有已編譯代碼的文件夾。上述源代碼在.\gmp\R\biginteger.R文件中找到。

相關問題