函数无法处理大的n值(接近400)

时间:2015-09-16 14:28:22

标签: haskell

这是来自统计项目。我定义了下面的函数,但是当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

1 个答案:

答案 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