簡體   English   中英

Haskell:f :: hex String - >使用尾遞歸的整數

[英]Haskell: f :: hex String -> Integer using tail recursion

我正在尋找一種使用尾遞歸將十六進制更改為整數的方法。 到目前為止,我只嘗試了常規原始遞歸的可怕實現,我甚至沒有接近。 非常沮喪。 甚至尾遞歸的例子也會有所幫助並且非常感激。 我對這個實現不太了解它。

例:

  • "005" -> 5
  • "1E" -> 30

限制:如果可能或尾遞歸,不能使用import或if,then,else等必須使用遞歸。

我嘗試遞歸。

    hexToInteger :: String -> Integer
        |(x:xs) = []        = []
        |x == 0             = hexToInteger xs
        |otherwise          = addition x + hexToInteger xs

    addition :: String -> Integer
    addition x 
        |--something to check what position we're dealing with and what hex value.
        |--Return the Integer value

通常,對於尾遞歸函數,您需要一個累加器參數 - 具有純度,否則結果只能取決於達到的基本情況。 所以你需要一個輔助函數,也需要一個累加器參數,並用累加器的初始值調用它,

hexToInteger :: String -> Integer
hexToInteger string = hexToIntegerHelper initialAccumulator string

你必須找到答案

  • 你應該為累加器傳遞什么初始值
  • 如何在每個步驟中更新累加器。

例如, reverse的尾遞歸實現是

reverse :: [a] -> [a]
reverse xs = reverseHelper [] xs

reverseHelper :: [a] -> [a] -> [a]
reverseHelper accumulator [] = accumulator
reverseHelper accumulator (x:xs) = reverseHelper (x:accumulator) xs

和一個尾遞歸因子(捏造負面論證的情況)

factorial :: Integer -> Integer
factorial n = factorialHelper 1 n

factorialHelper :: Integer -> Integer -> Integer
factorialHelper accumulator n
    | n < 2     = accumulator
    | otherwise = factorialHelper (n*accumulator) (n-1)

所以你可以看到hexToIntegerHelper的一般結構,

hexToIntegerHelper :: Integer -> String -> Integer
hexToIntegerHelper accumulator "" = accumulator
hexToIntegerHelper accumulator (d:ds) = hexToIntegerHelper (newAccumulatorFrom accumulator d) ds

問題是如何從舊的累加器和十六進制數字(以及初始累加器應該是什么)計算新的累加器。

為了更新累加器,

digitToInt :: Char -> Int

來自Data.Char可能很有用,它可以處理所有十六進制數字。 但是,它不會返回所需的類型,因此您需要使用fromIntegraltoIntegerInt轉換為Integer

這里有兩個遞歸函數,雖然已經向我指出它們不是尾遞歸的。 也許他們可以幫助你實現目標。

hexToInteger :: String -> Integer
hexToInteger [] = 0
hexToInteger str = 
  fromIntegral z + 16 * hexToInteger (init str)
    where z = let y = last str 
              in if y >= 'A' && y <= 'Z' 
                    then fromEnum y - 55 
                    else if y >= 'a' && y <= 'z'
                            then fromEnum y - 87
                            else fromEnum y - 48



hexToInteger :: String -> Integer
hexToInteger [] = 0
hexToInteger str = 
  z + 16 * hexToInteger (init str)
    where z = case last str of 
                '0' -> 0 
                '1' -> 1 
                '2' -> 2 
                '3' -> 3 
                '4' -> 4 
                '5' -> 5 
                '6' -> 6 
                '7' -> 7 
                '8' -> 8 
                '9' -> 9 
                'A' -> 10 
                'B' -> 11 
                'C' -> 12 
                'D' -> 13 
                'E' -> 14 
                'F' -> 15
                'a' -> 10 
                'b' -> 11 
                'c' -> 12 
                'd' -> 13 
                'e' -> 14 
                'f' -> 15
                otherwise -> 0

我們可以像在紙上轉換十六進制字符串一樣實現這一點:將輸出初始化為0,然后從左到右讀取字符串,每次將結果乘以16並添加新數字。

使用初始化為0的累加器參數創建並調用私有函數:

hex2int s = hex2int' s 0
    where

遞歸的基本情況采用空字符串並返回累加器:

        hex2int' "" n = n

遞歸情況采用字符串的第一個字符並相應地增加累加器。

        hex2int' (c:s) n = hex2int' s ((n * 16) + (hexDigit2int c))

hexDigit2int是一個簡單的查找。

        hexDigit2int c
          | c == "0" = 0

         ...

          | c == "f" = 15

暫無
暫無

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

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