这是来自统计项目。我定义了下面的函数,但是当n增长到接近400时,第二种方法很慢。第一种方法很好(这里有些人帮我in this question)
import Math.Combinatorics.Exact.Binomial -- from `exact-combinatorics` package
probaMet :: [Integer] -> Float-> Integer -> Float
probaMet [i,j] p n = sum [(p**fromIntegral l)*(fromIntegral(n `choose` l))*((1-p)**fromIntegral (n-l)) | l <- [i,i+1..j]]
indices :: [Int] -> Float-> Int -> [Int]
indices [] _ _ = [1,2]
indices [i,j] p n
| probaMet [toInteger i,toInteger j] p (toInteger n) >= beta = [i,j]
| otherwise = indices [(i-1),(j+1)] p n
我应该用n = 500进行计算,所以任何帮助都会很棒。这就是发生的事情
Main> indexEstadisticos [24,25] 0.25 100
[24,25]
*Main> indexEstadisticos [24,25] 0.25 250
[19,30]
*Main> indexEstadisticos [24,25] 0.25 400
答案 0 :(得分:5)
重新思考后,彻底改变了我的回答:
您的问题是您正在使用Float
,它只有单个浮点精度,并且已经0.25 ** 100 :: Float
等于0
,这意味着没有具有该高指数的术语将给出任何对总和的贡献。 0.75 == 1 - 0.25
会持续一段时间,但0.75 ** 400 :: Float
也是0
。
结果,你的总和太低了,在某些情况下很低,没有找到超过beta
的间隔,导致无限递归。
如果使用双精度Double
,则所有测试用例都将运行,第二个给出不同的答案。请注意,如果你在500
之上稍微远一点,即使Double
开始给出零。
附录:我再想一想,我以前的推理还是有点过时了。问题还涉及二项式系数变得太大大。当您的原始第二个案例回答[19,30]
时,probaMet
实际上返回了Infinity
值,而其他一些测试则将太大和太小都结合起来给予可怕的NaN
。但原因仍然是使用Float
。