我必须计算正确解码复制n
次的位的概率。
以下公式应该是答案:
在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
。有谁知道我哪里出错了?
答案 0 :(得分:6)
原因是功能优先。 如果你看一下prob的定义,你会看到:
(fac n-k)
因为函数应用程序具有最优先级,因此将其解析为
((fac n) - k)
所以你的代码应该是
(fac (n-k))
在我的电脑上得到0.999702的结果。
答案 1 :(得分:0)
这些是代码缺乏的几个最佳实践。我事实上已经回答了这个问题。
1-不要使用元组作为输入。在Haskell中,函数可以有多个参数。语法为f x y
,用于在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
同样适用。因此,prob infact的类型为(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
的参数(这是一个Integral实例),并返回类型为b
的值。< / p>