对无穷级数的有限前缀求和 [英] Summing a finite prefix of an infinite series

查看:129
本文介绍了对无穷级数的有限前缀求和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

π的数字可以通过以下无限序列和来计算:

The number π can be calculated with the following infinite series sum:

我想定义一个Haskell函数 roughlyPI ,在给定自然数 k 的情况下,该函数计算从 0 的序列和> k 值.

I want to define a Haskell function roughlyPI that, given a natural number k, calculates the series sum from 0 to the k value.

示例: roughlyPi 1000 (或其他)=> 3.1415926535897922

Example: roughlyPi 1000 (or whatever) => 3.1415926535897922

我所做的就是这个(在VS Code中):

What I did was this (in VS Code):

roughlyPI :: Double -> Double 
roughlyPI 0 = 2 
roughlyPI n = e1/e2 + (roughlyPI (n-1)) 
         where 
             e1 = 2**(n+1)*(factorial n)**2 
             e2 = factorial (2*n +1) 
             factorial 0 = 1 
             factorial n = n * factorial (n-1)

但是它并没有真正起作用....

but it doesn't really work....

*Main> roughlyPI 100 
NaN

我不知道怎么了.顺便说一下,我是Haskell的新手.

I don't know what's wrong. I'm new to Haskell, by the way.

我真正想要的是能够输入一个数字,该数字最后将给我 PI .没那么难...

All I really want is to be able to type in a number that will give me PI at the end. It can't be that hard...

推荐答案

如评论中所述,我们需要避免较大的划分,而应将较小的划分散布在阶乘中.我们使用 Double 表示PI,但即使 Double 也有其局限性.例如 1/0 == Infinity (1/0)/(1/0)== Infinity/Infinity == NaN .

As mentioned in the comments, we need to avoid large divisions and instead intersperse smaller divisions within the factorials. We use Double for representing PI but even Double has its limits. For instance 1 / 0 == Infinity and (1 / 0) / (1 / 0) == Infinity / Infinity == NaN.

幸运的是,我们可以使用代数来简化公式,并希望延迟 Double 的崩溃.通过将阶乘除以我们的阶乘,数字不会变得太笨拙.

Luckily, we can use algebra to simplify the formula and hopefully delay the blowup of our Doubles. By dividing within our factorial the numbers don't grow too unwieldy too quickly.

此解决方案将计算大约PI 1000 ,但由于 2 ^ 1024 :: Double == Infinity ,因此在1023上使用 NaN 时将失败.请注意, fac 的每次迭代如何进行除法和乘法运算以帮助防止数字爆炸.如果您尝试使用计算机来近似PI,我相信会有更好的算法,但是我试图在概念上尽可能地使其接近您的尝试.

This solution will calculate roughlyPI 1000, but it fails on 1023 with NaN because 2 ^ 1024 :: Double == Infinity. Note how each iteration of fac has a division as well as a multiplication to help keep the numbers from blowing up. If you are trying to approximate PI with a computer, I believe there are better algorithms, but I tried to keep it as conceptually close to your attempt as possible.

roughlyPI :: Integer -> Double
roughlyPI 0 = 2
roughlyPI k = e + roughlyPI (k - 1)
  where
    k' = fromIntegral k
    e = 2 ** (k' + 1) * fac k / (2 * k' + 1)
      where
        fac 1 = 1 / (k' + 1)
        fac p = (fromIntegral p / (k' + fromIntegral p)) * fac (p - 1)

通过使用

We can do better than having a blowup of Double after 1000 by doing computations with Rationals then converting to Double with realToFrac (credit to @leftaroundabout):

roughlyPI' :: Integer -> Double
roughlyPI' = realToFrac . go
  where
    go 0 = 2
    go k = e + go (k - 1)
      where
        e = 2 ^ (k + 1) * fac k / (2 * fromIntegral k + 1)
          where
            fac 1 = 1 % (k + 1)
            fac p = (p % (k + p)) * fac (p - 1)

有关更多参考,请参见有关PI近似值的维基百科页面

For further reference see Wikipedia page on approximations of PI

P.S.对不起笨重的方程式,stackoverflow不支持LaTex

P.S. Sorry for the bulky equations, stackoverflow does not support LaTex

这篇关于对无穷级数的有限前缀求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆