1

我想用递归来反转 Haskell 中的整数。我有一个小问题。

这是代码:

reverseInt :: Integer -> Integer
reverseInt n
|  n>0 = (mod n 10)*10 + reverseInt(div n 10)
|  otherwise = 0

示例 345

我用作输入 345 我想输出 543

在我的程序中它会做......

reverseInt 345
345>0
mod 345 10 -> 5
reverseInt 34
34
34>0
mod 34 10 -> 4
reverseInt 3
3>0
mod 3 10 -> 3
reverseInt 0
0=0 (ends)

最后它返回它们的总和...... 5 + 4 + 3 = 12。

所以我希望每次在对它们求和之前,乘以总和 * 10。所以它会......

5
5*10 + 4
54*10 + 3
543
4

6 回答 6

4

这是一个相对简单的:

reverseInt :: Int -> Int
reverseInt 0 = 0
reverseInt n = firstDigit + 10 * (reverseInt $ n - firstDigit * 10^place)
  where
    n' = fromIntegral n
    place = (floor . logBase 10) n'
    firstDigit = n `div` 10^place

基本上,

  1. 你把logBase 10你的输入整数,给你它在什么地方(10s,100s,1000s ...)
  2. 因为前面的计算给你一个浮点数,我们不需要小数,所以我们使用该floor函数截断小数点后的所有内容。
  3. 我们通过做来确定数字的第一位n 'div' 10^place。例如,如果我们有 543,我们会发现位置是 2,所以 firstDigit = 543/100 = 5(整数除法)
  4. 我们使用这个值,并将其添加到 10 * 整数“其余”的倒数,在本例中为 43。

编辑:也许更简洁易懂的版本可能是:

reverseInt :: Int -> Int
reverseInt 0 = 0
reverseInt n = mod n 10 * 10^place + reverseInt (div n 10)
  where
    n' = fromIntegral n
    place = (floor . logBase 10) n'

这一次,我们不是通过第一个数字递归,而是通过最后一个数字递归并使用 place 给它正确数量的零。

于 2013-11-06T10:28:49.917 回答
1
reverseInt :: Integer -> Integer
reverseInt n = snd $ rev n
               where
                 rev x
                   |  x>0 = let (a,b) = rev(div x 10)
                            in ((a*10), (mod x 10)*a + b)
                   |  otherwise = (1,0)

解释留给读者:)

于 2013-11-06T09:41:23.473 回答
1

(mod n 10)我不知道在第三行中找到应该乘以 10 多少次的便捷方法。我喜欢unfoldr更多的解决方案:

import Data.List
listify = unfoldr (\ x -> case x of
                             _ | x <= 0 -> Nothing
                             _          -> Just(mod x 10, div x 10) )

reverse_n n = foldl (\ acc x -> acc*10+x) 0 (listify n)

listify函数中,我们以相反的顺序从整数生成数字列表,然后我们构建结果简单折叠列表。

于 2013-11-06T09:44:41.720 回答
0

或者只是将其转换为字符串,将其反转并将其转换回整数:

 reverseInt :: Integer -> Integer
 reverseInt = read . reverse . show
于 2013-11-06T09:45:16.283 回答
0

更多(不一定基于递归)的答案非常好!

reverseInt 0 = 0
reverseInt x = foldl (\x y -> 10*x + y) 0 $ numToList x
  where
    numToList x = if x == 0 then [] else (x `rem` 10) : numToList (x `div` 10)

这基本上是两个函数的串联:numToList(将给定整数转换为列表 123 -> [1,2,3])和 listToNum(相反)。

numToList 函数通过重复获取数字的最低单位(使用remHaskell 的余数函数),然后将其截断(使用divHaskell 的整数除法函数)来工作。一旦数字为 0,则返回空列表并将结果连接到最终列表中。请记住,此列表是相反的顺序!

listToNum 函数(没见过)是一段相当性感的代码:

foldl (\x y -> 10*x + y) 0 xs

这从左边开始向右移动,将每一步的当前值乘以 10,然后将下一个数字加到它上面。

我知道答案已经给出,但看到替代解决方案总是很高兴:)

于 2013-11-06T11:10:42.023 回答
0

第一个函数是递归的,将整数转换为列表。它最初是反转的,但重新转换功能更容易反转,所以我把它从第一个中取出。这些功能可以单独运行。第一个输出一个元组对。第二个需要一个元组对。第二个不是递归的,也不需要递归。

di 0 ls = (ls,sum ls);  di n ls = di nn $ d:ls  where (nn,d) = divMod n 10
di 3456789 []

([3,4,5,6,7,8,9],42)

rec (ls,n) = (sum [y*(10^x)|(x,y) <- zip [0..] ls ],n)

两者都运行

rec $ di 3456789 []

(9876543,42)

于 2018-05-19T00:30:16.610 回答