我想找出所有2的幂除以10的列表!它显示异常,即除以零
[2^i | i<-[1..],(factorial(10) `mod` (2^i))==0]
完整的问题是获得函数largest_Power largest_Power :: Int - &gt; Int - &gt;诠释 maximum_Power n p 是除了n的最大p的幂! (n的阶乘)
我试着做这个
largest_Power :: Int->Int->Int
largest_Power 0 _ =1
largest_Power _ 0 =1
largest_Power n p = floor (logBase (fromIntegral p) (fromIntegral (last([p^i | i<-[1..],(factorial(n) `mod` (p^i))==0]))))
factorial::Int->Int
factorial 0=1
factorial 1=1
factorial x=x*factorial(x-1)
现在当我为maxowerPower 10 2运行时。我正在异常。
答案 0 :(得分:1)
Int
出了什么问题?好Int
有一个有限的范围 - 在大多数系统上-(2^63)
到2^63-1
。
现在你从1
(也是二进制的1
)开始,然后在二进制中添加零(与乘以2相同) - 你总是只有一个{{1} }后跟1
s。在某些时候你隐藏了下限的表示(最高位将表示正值或负值的标记),然后你将添加另一个0
,它会溢出0
结束你只有Int
s。
您可以轻松查看:
0
这就是原始答案中Prelude> take 64 $ [2^i | i <- [1..]] :: [Int]
[2,4,8,16,32,64,128,
...
,4611686018427387904,-9223372036854775808,0]
的来源。
你遇到的下一个问题是,列表理解
division by zero
将挂起并且不再生成任何值。
原因很简单:足够大[2^i | i<-[1..],(factorial(10) `mod` (2^i))==0]
:i
并且永远不会再划分它。
这就是我建议为2^i > factorial(10)
拉出过滤器并首先将列表限制为此硬限制的原因:
我不想一遍又一遍地写mod
所以我先定义
factorial 10
这是let m = product [1..10]
factorial 10
是[2^i | i <- [1..]]
2^i
才有趣,所以我们只考虑那些:m
takeWhile (<= m) [2^i | i <- [1..]]
没问题:filter
产生:
filter (\n -> m `mod` n == 0) $ takeWhile (<= m) [5^i | i <- [1..]]
当然事实证明你的问题是:
问题是要定义一个函数
的λ> let m = product [1..10] in filter (\n -> m `mod` n == 0) $ takeWhile (<= m) [2^i | i <- [1..]] [2,4,8,16,32,64,128,256]
largest_Power
largest_Power :: Int -> Int -> Int
是最大的largest_Power n p
分割p
factorial n
的力量
我现在假设你必须处理那里的Int
,所以你必须在某些fromIntegral
处理这些转换。
基于您的想法和上述代码段的解决方案可能是:
largest_Power :: Int -> Int -> Int
largest_Power n p = fromIntegral . last $ factorList n p
factorList :: Int -> Int -> [Integer]
factorList n p =
filter (\n -> m `mod` n == 0)
$ takeWhile (<= m) [p'^i | i <- [1..]]
where m = fromIntegral $ factorial n
p' = fromIntegral p
factorial :: Int -> Integer
factorial n = product [1..fromIntegral n]
如果您确实只对来自i
的{{1}}感兴趣,那么您可以将其推入元组并稍微调整算法:
p^i
程序的其余部分可以保持不变
现在,如果你想一想它发生了什么,老实说似乎没有意义,首先创建一个庞大的数字factorList :: Int -> Int -> [Integer]
factorList n p =
map fst
. filter (\(_,n) -> m `mod` n == 0)
$ takeWhile ((<= m) . snd) [(i,p'^i) | i <- [1..]]
where m = fromIntegral $ factorial n
p' = fromIntegral p
然后测试可分性,当我们需要的是我们可以划分这个数字的次数另一个(没有休息)当我们知道这个巨大的数字只是一个非常小的数字 - 因为我们可以检查较小的数字,然后加起来。
因此,如果您只对来自factorial n
的{{1}}感兴趣,那么也会这样做:
i
但对于更大的数字应该快得多。
请注意,如果您记住p^i
,如果这是在线竞赛的问题,您可以更快地获得这个...我怀疑^^