Döngüsüz toplama

Nov 12 2020

Aşağıdaki çift toplamaya sahibim: ∑10, i = 1 ∑i, j = 1 (i ^ 5 / (10 + j ^ i))

Bu alıştırmada oldukça kayboldum, aşağıdaki kodu denedim ama bana bir sayı vermesine rağmen bir hata döndürüyorum - kesinlikle doğru olmadığından eminim. Herhangi bir yardım çok değerlidir!

    i <- seq(1, 10, 1) 
    j <- seq(1, i, 1)
    denominators <- 10+j^i
    fractions <- (i^5)/denominators
    sum(fractions) 

veya

    i = rep(1:10, each=5)
    j = rep(i, 10) 
    sum(i^5/(10+j^i))

Yanıtlar

3 whuber Nov 12 2020 at 22:25

İç toplamın bir işlevini yapın:

f <- Vectorize(function(i) {
         j <- 1:i
         sum(i^5 / (10 + j^i))
     })

Üzerinde dış toplamı ne olduğunu: Bunu Vektörizasyonu siz o bileşen tarafından bileşen çalışacaktır diziler, uygulayabilirsiniz i yapmak söylüyor. Böylece değer

sum(f(1:10))

RAM israfına neden olan ve biraz daha yavaş olan başka bir çözüm, çift toplamın tüm terimlerini tek bir matriste hesaplamak için dış ürünü kullanır. Aşağıdakileri jaşmayan şartları çıkarmanız gerekir i:

n <- 10
x <- outer(1:n, 1:n, function(i,j) i^5 / (10 + j^i))
sum(x[!upper.tri(x)])

Yine de kompaktlığı ve basitliği için bilmek iyi bir tekniktir.

3 MrFlick Nov 12 2020 at 22:28

Tüm olası i / j kombinasyonlarını genişletebilir ve ardından tüm terimleri özetleyebilirsiniz.

i <- 1:10
ii <- rep(i, i)
jj <- unlist(sapply(i, function(x) seq(1,x)))
sum(ii^5/(10+jj^ii))
# [1] 20835.22
1 Onyambu Nov 12 2020 at 22:41

r'deki her şey vektörleştirilmiştir:

i <- seq(10)
j <- sequence(i)
i_use <- rep(i,i)

sum(i_use^5/(10 + j^i_use))
[1] 20835.22
1 MikkoMarttila Nov 13 2020 at 10:13

Bu şimdiye kadar oldukça kapsamlı bir şekilde yanıtlandı, ancak Map()/ kullanarak karışıma farklı bir teknikle başka bir çözüm atacağım Reduce():

i <- seq_len(10)
j <- lapply(i, seq_len)
Reduce("sum", Map(function(i, j) i^5 / (10 + j^i), i, j))
#> [1] 20835.22

Ve meraktan şu anda yayınlanan cevapların karşılaştırmaları. Tanımlar:

sum_vectorize <- function(n) {
  f <- Vectorize(function(i) {
    j <- 1:i
    sum(i^5 / (10 + j^i))
  })
  sum(f(1:n))
}

sum_outer <- function(n) {
  x <- outer(1:n, 1:n, function(i,j) i^5 / (10 + j^i))
  sum(x[!upper.tri(x)])
}

sum_sapply <- function(n) {
  i <- 1:n
  ii <- rep(i, i)
  jj <- unlist(sapply(i, function(x) seq(1,x)))
  sum(ii^5/(10+jj^ii))
}

sum_sequence <- function(n) {
  i <- seq(n)
  j <- sequence(i)
  i_use <- rep(i,i)
  
  sum(i_use^5/(10 + j^i_use))
}

sum_reduce <- function(n) {
  i <- seq_len(n)
  j <- lapply(i, seq_len)
  Reduce("sum", Map(function(i, j) i^5 / (10 + j^i), i, j))
}

Ve sonuçlar:

bench::press(
  n = c(10, 1000),
  {
    bench::mark(
      sum_vectorize(n),
      sum_outer(n),
      sum_sapply(n),
      sum_sequence(n),
      sum_reduce(n)
    )
  }
)
#> Running with:
#>       n
#> 1    10
#> 2  1000
#> Warning: Some expressions had a GC in every iteration; so filtering is disabled.
#> # A tibble: 10 x 7
#>    expression           n      min   median `itr/sec` mem_alloc `gc/sec`
#>    <bch:expr>       <dbl> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#>  1 sum_vectorize(n)    10   59.1us   69.4us  10307.     39.07KB    14.8 
#>  2 sum_outer(n)        10   18.1us   21.4us  35014.      49.8KB     7.00
#>  3 sum_sapply(n)       10   69.5us   88.8us   9044.      1.48KB    14.7 
#>  4 sum_sequence(n)     10   14.2us   16.3us  45303.      6.89KB     4.53
#>  5 sum_reduce(n)       10   32.6us   38.1us  20404.          0B    19.1 
#>  6 sum_vectorize(n)  1000    105ms  118.1ms      8.60    5.85MB     0   
#>  7 sum_outer(n)      1000  303.3ms  319.3ms      3.13    47.7MB     4.70
#>  8 sum_sapply(n)     1000  148.6ms  154.6ms      6.49   13.44MB     4.87
#>  9 sum_sequence(n)   1000  131.5ms  142.1ms      7.01   11.46MB     1.75
#> 10 sum_reduce(n)     1000  107.5ms    115ms      8.32    5.85MB     1.66