多数逻辑解码Haskell
问题描述:
我必须计算正确解码一个位复制n
次的概率。 下面的公式应该是答案:多数逻辑解码Haskell
在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
。有谁知道我错了哪里?
答
原因是功能优先。 ,如果你会去了解一下概率的定义,你会看到:
(fac n-k)
因为功能的应用程序具有最优先这个被解析为
((fac n) - k)
所以你的代码应该是
(fac (n-k))
在我的电脑上给出了0.999702的结果。
答
这些是代码缺乏的一些最佳实践。事实上我已经回答了这个问题本身。
1-不要使用元组作为输入。在Haskell中,函数可以有多个参数。在x
和y
上调用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
类型的值。
将epsilon作为'prob'的一个参数,我个人会围绕它制作一个包装函数,以便从传入的'n'中为我计算'k'。将epsilon调小一点,看看是不是问题所在是。 – bheklilr 2014-09-25 14:29:34
你为什么要评论这种类型? – user3329719 2014-09-25 15:14:37
这看起来像牛顿的binom公式 – user3329719 2014-09-25 15:15:34