2016-06-28 18 views
0

Rでは、ベクトルの長さ(bigzかどうか)を見つけるには、通常length関数を使用します。例えば。あなたがbigzベクトルを宣言した場合R:長さ関数を使用せずにbigzベクトルの長さを求める

NonBigZ <- 1:10 

NonBigZ 
[1] 1 2 3 4 5 6 7 8 9 10 

length(NonBigZ) 
[1] 10 

しかし、gmpパッケージを使用して、ベクトルの長さが自動的に返されます。例えば。

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が雷が速いと知っていますが、それを避けることができればかなり時間を節約することができます。お守り:私は無駄にattributes(BigZ)などstr(BigZ)を試してみました

system.time(sapply(1:10^6, function(x) length(BigZ))) 
user system elapsed 
7.81 0.00 7.84 

。私もgmpのドキュメントを読んでいますが、何も見つかりませんでした。

+1

'gmp ::: print.bigz'も' gmp ::: length.bigz'を使って 'length'を計算します。 'length.bigz'は' length'のような属性アクセス関数ではないようです。 'ns = c(1、10、50、100、200、500、1e3、5e3,1e4);を参照してください。 (ms)))$ median}); timings = sapply(ns、function(n){x = as.bigz(seq_len(n));サマリー(マイクロベンチマーク(長さ(x)、単位= "ms"プロット(ns、タイミング) '。私は、 "bigz"を作成するときに属性として "長さ"を保存する価値があるかもしれないと思います。 –

+0

あなたの質問にあなたの答えを載せるのではなく(あなたの質問を未解決のままにしておきます)、あなた自身の質問に答えてください。 – Gregor

+0

@ Gregor、私は私の答えが十分に徹底していたかどうか分からなかったので、答えとして掲示することに躊躇しました。 Anywho、私はあなたの提案をしました。 –

答えて

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) 
} 

が、それはあなたのbigzオブジェクトを返すようにcat機能を使用しています。 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' 

はジョシュアウルリッヒの素晴らしいquestionanswerを入力します。以下に示すコードを使用して、任意のパッケージのソースコードをダウンロードして1行に展開することができます。

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

これは、ディレクトリにコンパイル済みのコードをすべて含むフォルダを作成します。上記ソースコードは.\gmp\R\biginteger.Rファイルにあります。

関連する問題