2010-11-17 26 views
24

R. çalışırken ilginç bir şey fark ettim For döngüsü ve while-döngüsü kullanılarak uygulanan 1'den N'ye kadar kareleri hesaplayan basit bir programım olduğunda, davranış aynı. (Bu durumda vektörleştirmeyi umursamıyorum veya işlevleri uygula). For-loop vs while döngü içinde R

fn2 <- function (N) 
{ 
    i=1 
    while(i <= N) { 
     y <- i*i 
     i <- i + 1 
    } 
} 

fn1 <- function (N) 
{ 
    for(i in 1:N) { 
     y <- i*i 
    } 
} 

VE

sonuçlar şöyle:

system.time(fn1(60000)) 
    user system elapsed 
    2.500 0.012 2.493 
There were 50 or more warnings (use warnings() to see the first 50) 
Warning messages: 
1: In i * i : NAs produced by integer overflow 
. 
. 
. 

system.time(fn2(60000)) 
    user system elapsed 
    0.138 0.000 0.137 

Şimdi döngü için-hızlıdır, benim tahminim çünkü orada ön tahsisi ve optimizasyonlar sonucunda olduğunu biliyoruz. Ama neden taşıyor?

GÜNCELLEME:

fn3 <- function (N) 
{ 
    i <- 1:N 
    y <- i*i 
} 
system.time(fn3(60000)) 
    user system elapsed 
    0.008 0.000 0.009 
Warning message: 
In i * i : NAs produced by integer overflow 

Yani belki onun bir korkak bellek sorunu: Şimdi vektörler ile başka bir yol çalışıyor? OS X'de 4Gb bellek ve R'deki tüm varsayılan ayarlar ile çalışıyorum. Bu 32 ve 64-bit sürümlerde gerçekleşir (bu süreler daha hızlıdır).

Alex

+6

Zamanlama süresine bağlı olarak, döngü daha hızlıdır. – Marek

+2

Sayacı for döngüsünde bir float'a dönüştürdüğünüzde while döngüsünden daha hızlı olacaktır, ancak bunun nedeni for döngüsünün hiçbir uyarısı olmamasıdır. – John

+1

R, bu tür saçmalıklarla doludur. –

cevap

36

için 1 (yani, olan bir kayan nokta sayısı) sayısal değil, tam sayı olduğu ve 1:6000 sayısal ve tamsayıdır. Ancak

> as.integer(60000)*as.integer(60000) 
[1] NA 
Warning message: 
In as.integer(60000) * as.integer(60000) : NAs produced by integer overflow 

3,6 milyar kayan nokta kolayca sunulabilen: kare

> print(class(1)) 
[1] "numeric" 
> print(class(1:60000)) 
[1] "integer" 

60000 imzalanmış 32 bitlik tamsayı, dolayısıyla bir taşma hatası alıyorum gösterilemeyecek 3,6 milyar olduğu

:
> as.single(60000)*as.single(60000) 
[1] 3.6e+09 

bir kayan nokta gösterimi için dönüştürmek sizin for kodunu çözmek için

function (N) 
{ 
    for(i in as.single(1:N)) { 
     y <- i*i 
    } 
} 
+3

veya '((seq (1, N, 1)) i için ... –

+2

(N), 1: N'nin üzerinde tercih edilir: N- –

+0

@Joris veya "seq_len (N)" – Marek

4

değişken döngü için bir tamsayı dizisi, ve böylece en sonunda, bu do:

süre döngü bir kayan nokta sayısı oluşturma oysa
> y=as.integer(60000)*as.integer(60000) 
Warning message: 
In as.integer(60000) * as.integer(60000) : NAs produced by integer overflow 

.

Onun da nedeni bu durum farklı:

> seq(0,2,1) 
[1] 0 1 2 
> seq(0,2) 
[1] 0 1 2 

Bana inanmıyor musunuz?

> identical(seq(0,2),seq(0,2,1)) 
[1] FALSE 

için:

> is.integer(seq(0,2)) 
[1] TRUE 
> is.integer(seq(0,2,1)) 
[1] FALSE 
+0

Ancak neden yüzer noktaların tamsayılardan daha büyük bir aralığı var? – Alex

+1

GÜNCELLEME: "Hemen hemen tüm uygulamalarda, tamsayılan tamsayıların aralığı yaklaşık +/- 2 * 10^9 ile sınırlıdır: iki kat daha büyük tamsayıları tam olarak tutabilir." Tamsayı için R belgelerinden :( – Alex

+1

Çünkü bu kayan nokta FOR için –

3

Ve zamanlaması hakkında:

fn1 <- function (N) { 
    for(i in as.numeric(1:N)) { y <- i*i } 
} 
fn2 <- function (N) { 
    i=1 
    while (i <= N) { 
     y <- i*i 
     i <- i + 1 
    } 
} 

system.time(fn1(60000)) 
# user system elapsed 
# 0.06 0.00 0.07 
system.time(fn2(60000)) 
# user system elapsed 
# 0.12 0.00 0.13 

Ve şimdi For döngüsü while-döngü daha hızlı olduğunu biliyoruz. Zamanlama sırasında uyarıları göz ardı edemezsiniz.

+1

Bu döngü hala daha büyük gövdeye sahip olduğu için hala tam olarak adil değil; Bunun için öykünmek gerekir, biliyorum, ama bazı problemlerde durum böyle değil. – mbq

+2

@mbq For döngüsü ve while-döngüsü neden karşılaştırılamıyor. Her birinin farklı amacı vardır. 'Fn1'de' i <-i + 1' satırını ekleyebilir ancak yine de daha hızlı bir neden olabilir: 'fn2' koşulu kontrol etmek zorundadır, bu da <=' için 60k aramaları anlamına gelir. Başka bir satır eklerseniz, 'i <= N', 'fn1' için zamanlamalar eşittir. – Marek