多数逻辑解码Haskell

问题描述:

我必须计算正确解码一个位复制n次的概率。 下面的公式应该是答案:多数逻辑解码Haskell

the formula

在Haskell,我编码,如下所示:

fac 1 = 1 
fac n = fac (n-1) * n 
--prob :: (Integral b, Fractional b) => (b, b) -> b 
--prob :: (Int,Int) -> Double 
prob (n, k) 
    | n==k = (0.01**k) 
    | otherwise = factor (n, k) * (0.01 ** k) * (0.99**(n-k)) + prob (n, (k+1)) 
    where 
     factor (n, k) = (fac n/((fac k)* (fac n-k))) 

1 - prob (3,2)给出结果0.99992575,这是不正确的,因为它应该0.99970。有谁知道我错了哪里?

+1

将epsilon作为'prob'的一个参数,我个人会围绕它制作一个包装函数,以便从传入的'n'中为我计算'k'。将epsilon调小一点,看看是不是问题所在是。 – bheklilr 2014-09-25 14:29:34

+0

你为什么要评论这种类型? – user3329719 2014-09-25 15:14:37

+0

这看起来像牛顿的binom公式 – user3329719 2014-09-25 15:15:34

原因是功能优先。 ,如果你会去了解一下概率的定义,你会看到:

(fac n-k) 

因为功能的应用程序具有最优先这个被解析为

((fac n) - k) 

所以你的代码应该是

(fac (n-k)) 

在我的电脑上给出了0.999702的结果。

这些是代码缺乏的一些最佳实践。事实上我已经回答了这个问题本身。

1-不要使用元组作为输入。在Haskell中,函数可以有多个参数。在xy上调用f的语法是f x y。类型也有类似的语法。这将您的代码:

fac 1 = 1 
fac n = fac (n-1) * n 
--prob :: (Integral b, Fractional b) => b -> b -> b (two parameters of type b and output of type b) 
--prob :: Int -> Int -> Double 
prob n k 
    | n==k = (0.01**k) 
    | otherwise = factor n k * (0.01 ** k) * (0.99**(n-k)) + prob n (k+1) 
    where 
     factor n k = (fac n/((fac k)* (fac (n-k)))) 

2 - 如果你会发现,fac只能在整数的工作,同样不factor。概率事实上具有类型(Fractional a, Integral b) -> b -> b -> a或者Integer -> Integer -> Float。为什么不给他们自己的类型?

这种转化需要改变**(它可以获取两个浮点数)到^(它可以获取一个整数作为它的第二个参数),并使用该投射的整数的任意数量的数据的功能fromIntegral

fac :: Integral a => a -> a -- or alternatively Integer -> Integer 
fac 1 = 1 
fac n = fac (n-1) * n 
prob n k 
    | n==k = (0.01 ^^ k) 
    | otherwise = fromIntegral (factor n k) * (0.01 ^^ k) * (0.99 ^^ (n-k) + prob n (k+1) 
    where 
     factor n k = div (fac n) (fac k * fac (n-k)) -- div is Integer division operator. 

现在prob具有(Integral a, Floating b) => a -> a -> b类型,这意味着它得到a类型(这是一个积分实例)的两个参数,并返回b类型的值。