Suma sin bucles
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
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.
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
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
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