2014-09-25 131 views
0

我必須計算正確解碼一個位複製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

回答

6

原因是功能優先。 ,如果你會去了解一下概率的定義,你會看到:

(fac n-k) 

因爲功能的應用程序具有最優先這個被解析爲

((fac n) - k) 

所以你的代碼應該是

(fac (n-k)) 

在我的電腦上給出了0.999702的結果。

0

這些是代碼缺乏的一些最佳實踐。事實上我已經回答了這個問題本身。

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類型的值。