Performance 整数n的除数列表(Haskell)
我目前使用以下函数获取整数的除数:Performance 整数n的除数列表(Haskell),performance,haskell,primes,factors,factorization,Performance,Haskell,Primes,Factors,Factorization,我目前使用以下函数获取整数的除数: -- All divisors of a number divisors :: Integer -> [Integer] divisors 1 = [1] divisors n = firstHalf ++ secondHalf where firstHalf = filter (divides n) (candidates n) secondHalf = filter (\d -> n `div` d /= d) (m
-- All divisors of a number
divisors :: Integer -> [Integer]
divisors 1 = [1]
divisors n = firstHalf ++ secondHalf
where firstHalf = filter (divides n) (candidates n)
secondHalf = filter (\d -> n `div` d /= d) (map (n `div`) (reverse firstHalf))
candidates n = takeWhile (\d -> d * d <= n) [1..n]
——一个数的所有除数
除数::整数->[整数]
除数1=[1]
除数n=上半部分++下半部分
其中前半部分=过滤器(除以n)(n)
secondHalf=filter(\d->n`div`d/=d)(映射(n`div`)(反向上半部分))
候选者n=takeWhile(\d->d*d测量瓶颈所在,将三个辅助定义(前半部分、后半部分、候选者)放在顶层,并在分析器上运行代码:ghc-prof--make divisors.hs
/divisors 100+RTS-p-RTS
也知道,最大的候选是<代码> Sqt N,所以不要做很多乘法<代码> d*d>代码>,只考虑<代码> [1….Load(qrt n)] < /代码>
为了得到更好的算法,你应该带一本数学书,因为这不是一个与哈斯克尔有关的问题……你可以考虑的事情:如果“a除以b”,那么对于a的所有除数d,d也除以b。 如果给定的d除以b,您需要使用记忆或动态编程来避免多次检查(例如,如果15和27除以b,那么您只需要在数学上检查3除以b一次。其他时候,您只需查看3是否在b的除数表中).您不必测试反向后半部分的所有元素。您知道,如果平方根存在,那么它就是那里的头元素: secondHalf = let (r:ds) = [n `div` d | d <- reverse firstHalf]
in [r | n `div` r /= r] ++ ds
这样我们就可以免费获得下半场,作为制作上半场的一部分
但这很难成为应用程序中的瓶颈,因为算法本身效率很低。通常更快。通过尝试除法进行素因子分解可以更快,因为我们将发现的每个除数进行除法,从而减少被分解的数,从而减少尝试的除数(直到减少的数字的平方根)。例如,12348=2*2*3*3*7*7
并且在分解过程中不尝试高于7
的因子,而在divs 12348
中,数字12348被从2
到110
的所有数字所除:
factorize n=go n(2:[3,5..])--或:(go n素数)其中
其中--primes=2:
go n ds@(d:t)——过滤器(null.tail.factorize)[3,5..]
|d*d>n=[n]
|r==0=d:go q ds
|否则=去
式中(q,r)=quotRem n d