我一直在尝试解决一个需要Sigma Notation的问题(或者至少我认为),但是我遇到的Haskell中Sigma Notation的每个实现都没有在其函数中使用索引变量。我一直试图复制的特定公式是:
它用于计算n!中的尾随零的数量,但我得到的最好的是:
sigma :: (Enum a, Num b) => a -> a -> (a -> b) -> b
sigma i k fn = sum . map fn $ [i..k]
zeros :: Int -> Int
zeros n = sigma 1 n (???)
我正在尝试创建一个通用的sigma函数,它与f中的索引变量一起使用。 这有效,但对于100 !,它给出-11尾随零。溢出?
zeros :: Int -> Int
zeros n = sigma 1 n (\i -> n `div` 5 ^ i)
where sigma i k fn = sum $ map fn [i..k]
P.S。我在浏览器中限制编译时间的IDE。 (所以速度很重要)
答案 0 :(得分:2)
你的麻烦只来自类型不匹配。您希望在最后执行truncate
并使用小数运算进行除法,取幂和求和,然后在结尾处截断结果。因此,您需要的不仅仅是zeros n = sigma 1 n something
:
zeros :: Integral a => a -> a
zeros n = truncate $ sigma 1 n (\i -> fromIntegral n / 5 ^ i)
您需要担心的详细信息是fromIntegral n
,它将n
从Integral a => a
转换为Num b => b
,^
运算符允许{ {1}}参数作为指数,因此我们不需要在那里进行转换,然后Integral a => a
将转换回truncate
。我们可以使这个签名更加通用,并返回我们输入的不同Integral
,但这在实践中并没有用。
现在我们可以输入Integral
或Int
,具体取决于您需要输入此函数的数量的大小(因为您提到了Integer
),但请注意制作100!
元素列表会严重占用RAM和CPU时间。
如果你真的想要计算大数的尾随零,那么将它转换为字符串可能要容易得多,如:
100!
答案 1 :(得分:1)
sigma i k fn = sum $ map fn [i..k]
zeros n = sigma 1 n (\i -> fromIntegral n / 5**(fromIntegral i))
Haskell不会自动在整数和浮点数之间进行转换。这就是您需要fromIntegral
。