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それがどの位置にあるかを示します (10 秒、100 秒、1000 秒...)
  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'

今回は、最初の数字を再帰する代わりに、最後の数字を再帰し、正しい数のゼロを与えるために場所を使用しています。

于 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)3 行目に 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 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)

これは基本的に 2 つの関数を連結したものです。

numToList 関数は、( remHaskell の剰余関数を使用して) 数値の最小単位を繰り返し取得し、( divHaskell の整数除算関数を使用して) 切り捨てることによって機能します。数値が 0 になると、空のリストが返され、結果が最終的なリストに連結されます。このリストは逆順になっていることに注意してください。

listToNum 関数 (表示されていません) は非常に魅力的なコードです。

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

これは、左から開始して右に移動し、各ステップで現在の値を 10 倍してから、次の数値を加算します。

答えはすでに与えられていることは知っていますが、別の解決策を見るのはいつでもいいことです:)

于 2013-11-06T11:10:42.023 に答える