2012-03-25 49 views
1

我遇到了一個簡單的Haskell程序問題。它應該將數字n-1分解成(2^r)s形式,其中n是卡邁克爾數。這與我的問題並不緊密相關,但它是以下功能集的目的所在。Haskell數字類型挫折

divides::Int->Int->Bool 
divides x y = not $ y `mod` x == 0 

carmichaeltwos::Int->Int 
carmichaeltwos n 
    | not $ divides 2 n =0 
    | otherwise = (+ 1) $ carmichaeltwos (n/2) 

carmichaelodd::Int->Int 
carmichaelodd n 
    | not $ divides 2 n = n 
    | otherwise = carmichaelodd (n/2) 

factorcarmichael::Int->(Int, Int) 
factorcarmichael n = (r, s) 
    where 
     nminus = n-1 
     r = carmichaeltwos nminus 
     s = carmichaelodd nminus 

當我嘗試這個加載到GHCI,Haskell中吐奶:

No instance for (Fractional Int) 
    arising from a use of `/' 
Possible fix: add an instance declaration for (Fractional Int) 
In the first argument of `carmichaelodd', namely `(n/2)' 
In the expression: carmichaelodd (n/2) 
In an equation for `carmichaelodd': 
    carmichaelodd n 
     | not $ divides 2 n = n 
     | otherwise = carmichaelodd (n/2) 

我知道的功能/已鍵入(/)::(一分數)=> A->一 - > a,但我看不出如何修復我的程序以使其很好地工作。

另外,我意識到我基本上在factorcarmichael函數中計算兩次相同的東西。我想不出任何簡單的方法來將數字分解成一個通道,並得到我想要的元組作爲答案。

+2

jwodder,說明了他們的答案最好的解決辦法,但值得注意的是,你可以用'fromIntegral'轉換的'實例Integral'到'Fractional'和'round' /'floor' /'ceiling' /'truncate'的實例中,以轉換RealFrac的一個實例(比如'Float','Double','Rational'等等)轉換爲'Integral'的實例。 – ehird 2012-03-25 19:10:14

回答

5

分隔兩個Int此時你會知道,在這種情況下,分紅是整除除數,使用divquot功能,即div n 2quot n 2。 (divquot當「真正的」商不是整數區別僅僅在於他們處理負面操作數)。

而且,你爲什麼定義爲dividesnot $ mod y x == 0?除非您使用非標準的「分頻」含義,否則您應該只使用mod y x == 0 - x除以y iff ymodulox爲零。

至於合併carmichaeltwoscarmichaelodd,請嘗試使用until功能:

factorcarmichael n = until (\(_, s) -> not $ divides 2 s) 
          (\(r, s) -> (r+1, div s 2)) 
          (0, n-1) 
+2

糟糕。我有點兒醉了。你對分歧是正確的。 – 2012-03-25 19:10:33

+3

@Josh另外,對於2的可分性,有「偶數」和「奇數」。 – 2012-03-25 20:19:33