Haskell:一个非常大的数字的最后一位数

时间:2017-08-05 15:22:32

标签: haskell

我试图弄清楚一个非常大的数字的最后一个数字。我遇到的挑战是错误

*** Exception: Prelude.!!: negative index

我认为应该不可能。当我尝试时会发生这种情况:

lastDigit [27,15,14]

以下是我的代码,该代码基于https://brilliant.org/wiki/finding-the-last-digit-of-a-power/

在这种情况下,n变为7,modList 7给出重复序列[1,7,9,3,1,7,9,3 ...],这是(!!)中的第一个参数相关警卫。 (!!)的第二个参数给出1,因为(y:ys)是(15,14)而rem(powers(15 ^ 14))4是1.请帮助。

lastDigit :: [Integer] -> Integer 
lastDigit [] = 1 
lastDigit [x] = x `mod` 10 
lastDigit [x,y] = x ^ y `mod` 10
lastDigit (x:y:ys) 
 | y == 0 && head ys /= 0 = 1
 | n == 0 = 0
 | n == 9 || n == 4 = (!!) (modList n) (rem (fromIntegral $ powers (y:ys)) 2) 
 | n == 2 || n == 3 || n == 7 || n == 8 = (!!) (modList n) (rem (fromIntegral $ powers (y:ys)) 4)
 | otherwise = n
    where n = mod x 10 
         powers xs = foldr1 (^) xs
         modList n = drop 3 . take 30 $ cycle [mod x 10| x <- map (n^) $ take 4 [1..]]

1 个答案:

答案 0 :(得分:1)

您应该对类型非常具体,否则它们可能会在计算过程中被隐式转换。如果将Int类型添加到算法中,ghc将不会抱怨并遇到负索引异常

(fromIntegral $ powers (y:ys)) 2 :: Int)

但如果你提供

(fromIntegral $ powers (y:ys)) 2 :: Integer)

将导致

• Couldn't match expected type ‘Int’ with actual type ‘Integer’
• In the second argument of ‘(!!)’, namely
    ‘(rem (fromIntegral $ powers (y : ys)) 2 :: Integer)’

正如您所看到的,那里有一个隐式的Int转换。尝试将您的函数拆分为较小的函数并提供类型签名,然后您应该能够成功对齐类型并使用Integers而不是Int进行计算。