Summation ohne Schleifen
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
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.
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
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
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