Summation without loops

后端 未结 4 912
孤街浪徒
孤街浪徒 2021-01-21 15:11

I have following double summation: ∑10,i=1 ∑i,j=1 (i^5/(10+j^i))

I am quite lost with this exercise, I tried the following code but I it returns an error although giving

相关标签:
4条回答
  • 2021-01-21 15:26

    This has been fairly thoroughly answered by now, but I’ll throw another solution in the mix with a different technique, using 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
    

    And out of curiosity, benchmarks of the currently posted answers. Definitions:

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

    And the results:

    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
    
    0 讨论(0)
  • 2021-01-21 15:27

    everything in r is vectorized:

    i <- seq(10)
    j <- sequence(i)
    i_use <- rep(i,i)
    
    sum(i_use^5/(10 + j^i_use))
    [1] 20835.22
    
    0 讨论(0)
  • 2021-01-21 15:38

    You could expand all the possible i/j combinations and then sum up all the terms

    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
    
    0 讨论(0)
  • 2021-01-21 15:39

    Make a function of the inner sum:

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

    By vectorizing it you can apply it to arrays, where it will operate component by component: that's what the outer sum over i says to do. Thus, the value is

    sum(f(1:10))
    

    Another solution, wasteful of RAM and a bit slower, exploits the outer product to compute all the terms of the double sum in one matrix. You have to extract the terms for which j does not exceed i:

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

    For its compactness and simplicity, though, it's a good technique to know.

    0 讨论(0)
提交回复
热议问题