多数逻辑译码Haskell

多数逻辑译码Haskell,haskell,logic,decoding,Haskell,Logic,Decoding,我必须计算一个比特被复制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.

我必须计算一个比特被复制
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
。有人知道我哪里出错了吗?

原因是函数优先级。 如果你仔细研究prob的定义,你会发现:

(fac n-k)
因为函数应用程序的优先级最高,所以将其解析为

((fac n) - k)
所以你的代码应该是

(fac (n-k))

这在我的计算机上给出了0.999702的结果。

原因是函数优先级。 如果你仔细研究prob的定义,你会发现:

(fac n-k)
因为函数应用程序的优先级最高,所以将其解析为

((fac n) - k)
所以你的代码应该是

(fac (n-k))

这在我的计算机上给出了0.999702的结果。

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

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

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的类型为
(分数a,整数b)->b->b->a
,或者
整数->整数->浮点
。为什么不给他们真实的类型呢?

此转换需要将
**
(获取两个浮点数)更改为
^
(获取一个整数作为第二个参数),并使用函数
from integral
,将整数转换为任意数数据

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
的类型为
(整数a,浮动b)=>a->a->b
,这意味着它获取两个
a
类型的参数(这是一个整数实例),并返回类型为
b
的值。这些是代码缺少的两个最佳实践。事实上,我已经回答了这个问题。

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

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的类型为
(分数a,整数b)->b->b->a
,或者
整数->整数->浮点
。为什么不给他们真实的类型呢?

此转换需要将
**
(获取两个浮点数)更改为
^
(获取一个整数作为第二个参数),并使用函数
from integral
,将整数转换为任意数数据

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
的类型为
(整数a,浮动b)=>a->a->b
,这意味着它获取两个
a
类型的参数(这是一个整数实例),并返回类型为
b

的值,将εa参数设置为
prob
,我个人会在它周围做一个包装,根据传入的
n
为我计算
k
。把ε调小一点,看看问题是否出在这里。你为什么要注释掉这个类型?这看起来太像牛顿的比诺姆了formula@user3329719它们非常相关:此公式使用a计算
(n+1)/2
或更多错误的概率。将ε作为
prob
的参数,我个人会在它周围做一个包装,根据传入的
n
为我计算
k
。把ε调小一点,看看问题是否出在这里。你为什么要注释掉这个类型?这看起来太像牛顿的比诺姆了formula@user3329719它们是非常相关的:这个公式计算出
(n+1)/2
或更多错误的概率。