Somme sans boucles

Nov 12 2020

J'ai la double sommation suivante: ∑10, i = 1 ∑i, j = 1 (i ^ 5 / (10 + j ^ i))

Je suis assez perdu avec cet exercice, j'ai essayé le code suivant mais il renvoie une erreur tout en me donnant un numéro - à peu près sûr que ce n'est pas correct. Toute aide est grandement appréciée!

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

ou

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

Réponses

3 whuber Nov 12 2020 at 22:25

Faire une fonction de la somme intérieure:

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

En le vectorisant, vous pouvez l'appliquer à des tableaux, où il fonctionnera composant par composant: c'est ce que la somme externe sur i dit de faire. Ainsi, la valeur est

sum(f(1:10))

Une autre solution, gaspilleuse de RAM et un peu plus lente, exploite le produit externe pour calculer tous les termes de la double somme dans une matrice. Vous devez extraire les termes pour lesquels jne dépasse pas i:

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

Pour sa compacité et sa simplicité, cependant, c'est une bonne technique à connaître.

3 MrFlick Nov 12 2020 at 22:28

Vous pouvez développer toutes les combinaisons i / j possibles, puis résumer tous les termes

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

tout dans r est vectorisé:

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

Cela a été assez bien répondu maintenant, mais je vais jeter une autre solution dans le mélange avec une technique différente, en utilisant Map()/ 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

Et par curiosité, repères des réponses actuellement publiées. Définitions:

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

Et les résultats:

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