簡體   English   中英

haskell:自然數的因子

[英]haskell: factors of a natural number

我正在嘗試在Haskell中編寫一個函數,該函數計算給定數字以外的所有因子。

結果應如下所示:

factorlist 15 => [1,3,5]

我是Haskell和整個遞歸主題的新手,我很確定我可以在此示例中應用它,但是我不知道在哪里或如何使用。

我的想法是使用mod函數將給定數字與1到n div 2列表中的第一個元素進行比較,但是以某種方式遞歸進行比較,如果結果為0則將數字添加到新列表中。 (我希望這有道理)

我將不勝感激

到目前為止,這是我的代碼:(它不起作用..但是以某種方式說明了我的想法)

 factorList :: Int -> [Int]
 factorList n  |n `mod` head [1..n`div`2] == 0 = x:[]

有幾種方法可以解決此問題。 但首先,讓我們寫一個小的小助手:

isFactorOf :: Integral a => a -> a -> Bool
isFactorOf x n = n `mod` x == 0

這樣,我們可以將12 `isFactorOf` 24寫入TrueFalse 對於遞歸部分,假設我們使用一個帶有兩個參數的函數:一個是我們要分解的數字,第二個是我們目前正在測試的因子。 我們僅測試n `div` 2或等於n `div` 2因子,這將導致:

createList n f | f <= n `div` 2 = if f `isFactorOf` n
                                     then f : next
                                     else next
               | otherwise      = []
    where next = createList n (f + 1)

因此, 如果第二個參數是n的因數,則將其添加到列表中並繼續,否則就繼續。 只要f <= n `div` 2我們就這樣做。 現在,為了創建factorList ,我們可以簡單地使用createList有足夠的第二個參數:

factorList n = createList n 1

遞歸隱藏在createList 因此, createList工人 ,你可以把它藏在一個where的內部factorList

請注意,可以使用過濾器或列表factorList輕松定義factorList

factorList'  n = filter (`isFactorOf` n) [1 .. n `div` 2]
factorList'' n = [ x | x <- [1 .. n`div` 2], x `isFactorOf` n]

但是在這種情況下,您自己不會編寫遞歸。

進一步練習:

  • 嘗試自己實現filter功能。
  • 創建另一個僅返回因子的函數。 您可以使用以前的結果並編寫質數過濾器,也可以編寫直接生成結果的遞歸函數(后者更快)。

@Zeta的答案很有趣。 但是,如果您像我一樣是Haskell的新手,那么您可能希望以一個“簡單”的答案開始。 (只是獲得基本的遞歸模式...並了解縮進以及類似的內容。)

我不會將任何東西除以2,而是將數字本身包括在內。 因此,在我的示例中, factorlist 15 => [1,3,5,15]

factorList :: Int -> [Int]

factorList value = factorsGreaterOrEqual 1
  where
    factorsGreaterOrEqual test
      | (test == value) = [value]
      | (value `mod` test == 0) = test : restOfFactors
      | otherwise = restOfFactors
      where restOfFactors = factorsGreaterOrEqual (test + 1)

第一行是類型簽名,您已經知道。 類型簽名不必位於函數的模式定義列表的旁邊 (盡管模式本身需要在順序行上全部組合在一起)。

然后,根據輔助函數定義factorList 此輔助函數在where子句中定義...表示這是局部函數, 可以訪問value參數 如果我們全局定義factorGreaterOrEqual,那么它將需要兩個參數,因為value不在范圍內,例如

factorsGreaterOrEqual 4 15 => [5,15]

您可能會說,factorsGreaterOrEqual本身就是一個有用的函數。 也許是,也許不是。 但是在這種情況下,我們要說的是除了幫助我們定義factorList以外,它不是一般用途...因此使用where子句並隱式地獲取值更干凈。

從我的角度來看,Haskell的縮進規則很奇怪,但是這里對它們進行了總結 我在這里縮進兩個空格,因為如果使用4,它會增長得太遠。

在Haskell中,前面帶有該豎線字符的布爾測試列表稱為“守衛”。 我只是將最終條件設置為測試達到值時的狀態。 因此,如果我們正在調用factorList NfactorsGreaterOrEqual N = [N] 然后,我們通過將值除以沒有余數來決定是否將測試號連接到列表中。 otherwise為Haskell關鍵字,對於掉線default ,類似C的switch語句中的default

為了展示另一個層次的嵌套和另一個隱式參數演示,我添加了一個where子句以本地定義一個名為restOfFactors的函數。 無需將test作為參數傳遞給restOfFactors,因為它位於“ factorsGreaterOrEqual ”的范圍內...並且因為它位於factorList的范圍內, factorList值也可用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM