I am trying to sum all n from 1 to a very large number (10**9 for now) but it gives stack overflow. Also I don't think putting a stop at 1 and doing the sum n in different rows is the most efficient way but the code below is all my knowledge for Haskell. I really don't know much about functional programming and I would like as much explanation as possible. (Also I have tried putting $! strict in the last line which was told in other places but it changed nothing. I would be glad if you explained the most efficient way I could do this recursive function.)
main :: IO()
summ 1 = 1
summ n = 1/(n**2) + summ (n-1)
expected_value = pi*pi/6
errorPercent n = n / expected_value * 100
main = do
putStr "%"
print (errorPercent (summ $! (10**9)))
The problem here is that sums can not start being computed until the whole 10^9 recursion calls are over. Essentially, you are computing
1/(n**2) + ( 1/((n-1)**2) + ( 1/((n-2)**2) + ....
and the parentheses prevent to start summing. Instead, we would like to have
(( 1/(n**2) + 1/((n-1)**2) ) + 1/((n-2)**2) ) + ....
The easiest way is to use an "accumulator" additional argument:
summ 1 acc = 1 + acc
summ n acc = summ (n-1) $! acc + 1/(n**2)
main = do
putStr "%"
print (errorPercent (summ (10^9) 0)) -- set acc to 0 at the beginning
For improving the performance, I'd recommend to add a type signature to summ
e.g. summ :: Int -> Double -> Double
.
Full program below. This runs in 12s here (ghc -O2
).
summ :: Int -> Double -> Double
summ 1 acc = 1 + acc
summ n acc = summ (n-1) $! acc + 1 / (fromIntegral n**2)
main :: IO ()
main = do
putStr "%"
print (summ (10^9) 0) -- set acc to 0 at the beginning