bub*_*ubu 1 integration haskell
我正在尝试在Haskell中定义梯形规则.我创建了一个辅助函数innerSum,它是梯形规则的总和部分.然后在积分定义中我乘以距离乘以下界,上界,一个函数和一些n个梯形.随着n增加,答案应该变得更准确.我的功能似乎适用于大多数情况
除了这种情况(可能还有其他情况):definiteIntegral(-1)1(\ x-> x ^ 100)20.
当我将值改为20而不是我的答案偏离某个并且变得更准确时,数字会随机跳转.我似乎无法找到错误
definiteIntegral :: Double -> Double -> (Double -> Double) -> Integer -> Double
definiteIntegral a b g n | a <= b = (dist a b n)*(innerSum a b g (dist a b n))
| otherwise = (dist a b n)*(innerSum b a g (dist b a n))
where dist a b n = (b-a)/(fromIntegral n::Double)
innerSum :: Double -> Double -> (Double -> Double) -> Double -> Double
innerSum a b g d | a >= b = 0
| otherwise = (((g a) + (g (a + d)))/2)+(innerSum (a + d) b g d)
Run Code Online (Sandbox Code Playgroud)
问题是你的最终状况.您计算步长原则上,您应该在n步骤之后准确地在右边界处结束.事实上,如果确保步长可以用浮点精确表示,即2的幂的倍数,那么这将有效:
*Main> definiteIntegral (-1) 1 (^100) <$> [64, 128, 256, 512, 1024]
[3.396429282002939e-2,2.3718601030590182e-2,2.08093271780123e-2,2.0055667986086628e-2,1.9865519301509465e-2]
-- convergence towards 1.98×10?²
Run Code Online (Sandbox Code Playgroud)
但大多数的数字可以不完全以FP代表,所以你会经常不能准确地击中了右边界.如果最后一个点略微偏离该界限,算法将执行一个额外的步骤,即您将一个小的浮动不准确性炸成整个步骤的不准确性.从数字上讲,它只是一个1阶错误,因为随着您提高分辨率,单个步长变得越来越小.(它仍然很糟糕,因为梯形规则实际上应该是二阶准确的!)
(^100)特别的问题是:该函数在大多数区间[-1,1]上非常接近零,但在±1附近非常快速地增长.因此,区间的结果由边界旁边的梯形支配,甚至更多的是由边界外的梯形支撑!
最简单的解决方法是删除该innerSum功能并使用内置工具:
definiteIntegral :: Double -> Double -> (Double -> Double) -> Integer -> Double
definiteIntegral a b g n
| a <= b = - definiteIntegral b a g n
| otherwise = ? * sum [ (g x + g (x+?))/2
| x <- [a, a+? .. b] ]
where ? = (b-a) / fromIntegral n
Run Code Online (Sandbox Code Playgroud)
在这个问题中解释了为什么即使步长没有精确表示也能正常工作:[a, a+? .. b]如果前一个已经接近边界而下一个步骤远远超出边界,则浮动范围就像拒绝采取额外步骤.
| 归档时间: |
|
| 查看次数: |
274 次 |
| 最近记录: |