Suma sin bucles

Nov 12 2020

Tengo la siguiente suma doble: ∑10, i = 1 ∑i, j = 1 (i ^ 5 / (10 + j ^ i))

Estoy bastante perdido con este ejercicio, probé el siguiente código pero devuelve un error aunque me da un número, bastante seguro de que no es correcto. ¡Cualquier ayuda es muy apreciada!

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

o

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

Respuestas

3 whuber Nov 12 2020 at 22:25

Haz una función de la suma interna:

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

Al vectorizarlo, puede aplicarlo a matrices, donde operará componente por componente: eso es lo que dice la suma externa sobre i . Por tanto, el valor es

sum(f(1:10))

Otra solución, que desperdicia RAM y un poco más lenta, aprovecha el producto externo para calcular todos los términos de la doble suma en una matriz. Tienes que extraer los términos para los que jno exceda i:

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

Sin embargo, por su compacidad y simplicidad, es una buena técnica para conocer.

3 MrFlick Nov 12 2020 at 22:28

Puede expandir todas las combinaciones posibles de i / j y luego sumar todos los términos

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

todo en r está vectorizado:

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

Esto ya se ha respondido bastante a fondo, pero agregaré otra solución a la mezcla con una técnica diferente, usando 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

Y por curiosidad, puntos de referencia de las respuestas publicadas actualmente. Definiciones:

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

Y los resultados:

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