Summation ohne Schleifen

Nov 12 2020

Ich habe folgende Doppelsummation: ∑10, i = 1 ∑i, j = 1 (i ^ 5 / (10 + j ^ i))

Ich bin ziemlich verloren mit dieser Übung, ich habe den folgenden Code ausprobiert, aber ich gebe einen Fehler zurück, obwohl ich eine Nummer habe - ziemlich sicher, dass er nicht korrekt ist. Jede Hilfe wird sehr geschätzt!

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

oder

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

Antworten

3 whuber Nov 12 2020 at 22:25

Machen Sie eine Funktion der inneren Summe:

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

Indem Sie es vektorisieren, können Sie es auf Arrays anwenden, wo es Komponente für Komponente betrieben wird: Das ist, was die äußere Summe über i zu tun sagt. Somit ist der Wert

sum(f(1:10))

Eine andere Lösung, die RAM verschwendet und etwas langsamer ist, nutzt das äußere Produkt, um alle Terme der Doppelsumme in einer Matrix zu berechnen. Sie müssen die Begriffe extrahieren, die jnicht überschreiten i:

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

Aufgrund seiner Kompaktheit und Einfachheit ist es jedoch eine gute Technik zu wissen.

3 MrFlick Nov 12 2020 at 22:28

Sie können alle möglichen I / J-Kombinationen erweitern und dann alle Begriffe zusammenfassen

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

alles in r ist vektorisiert:

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

Dies wurde inzwischen ziemlich gründlich beantwortet, aber ich werde eine andere Lösung mit einer anderen Technik in die Mischung werfen, wobei Map()/ verwendet wird 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

Und aus Neugier Benchmarks der aktuell veröffentlichten Antworten. Definitionen:

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

Und die Ergebnisse:

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