第n个素数和素因数

时间:2018-11-16 11:53:10

标签: haskell

在浏览Haskell教程时,它说要编写一个函数“ isPrime”来确定数字是否为质数。

我想到了:

public JsonResult GetAllPanditBookList()
{
    var plist= db.TB_PBooking.Select(hc => new { 
        hc.PB_ID, 
        hc.PB_PRICE, 
        hc.PB_SPRICE, 
        hc.USER_ID,  
        hc.REG_DATE, 
        hc.STATUS,
        ((hc.PB_PRICE *hc.PB_SPRICE) /100) as FinalPrice,
        hc.PAYMENT_TYPE,
        hc.TB_UserReg.FULL_NAME,
        USERMOB=hc.TB_UserReg.MOBILE_NO 
    }).OrderByDescending(x => x.PB_ID).ToList();

    return Json(_templeList, JsonRequestBehavior.AllowGet);
}

有效。

但是我该如何求第n个素数-例如,第100个素数是541?

进一步研究素数,我发现了像这样的素因数列表:

isPrime :: Integer -> Bool
isPrime n = factors n == [1,n]
    where factors n = [x | x <- [1..n], n `mod` x == 0]

这同样适用。

但是,当您输入大量数字时,您会得到明显的滞后时间。

作为示例,它可以很好地完成这些操作:

primeFactors :: Integer -> [Integer]
primeFactors n = filter prime (factors n)
    where factors n = [x | x <- [1..n], n `mod` x == 0]
          prime n = factors n == [1,n]

该教程建议找到62451532000的主要因素,在那附近,大约5分钟后,我仍在等待。

是什么导致延迟时间?什么是最快的延迟时间?

3 个答案:

答案 0 :(得分:5)

滞后时间归因于因子功能。从1迭代到n。因此,如果n62451532000,则至少会有62451532000个步骤。步骤太多了。

有很多方法可以加快速度。实际上有很多人可以写一本书。我建议您查找分解。

现在,尝试实现此简单技巧。每当dn的因数时,n/d也是如此。如果您寻找√n以下的所有因素,并利用此技巧,您将找到所有因素。

这会将所需的步骤数从62451532000减少到约250000。更易于管理。

答案 1 :(得分:1)

您可以轻松摆脱prime。算法中的微小变化足以确保您发现的任何新因素都可以保证是首要的。

这是您的操作方式。每次找到x除以n时,就从x中删除所有n因子,然后继续使用该新值。

考虑下面的数字40示例。请注意40 = 2 ^ 3 * 5。因此40被1、2、4、5、8、20和40整除。我们从2开始测试素因数。

40 `mod` 2 == 0 

所以2是一个因数(也是素数)。因此,我们删除所有2的

40 `mod` 2 == 0
40 `div` 2 == 20

20 `mod` 2 == 0
20 `div` 2 == 10

10 `mod` 2 == 0
10 `div` 2 == 5

5 `mod` 2 == 1

因此,我们从40中删除了所有2,直到得到5。现在我们改为5。您先检查除以3,然后除以4,然后乘以5即可。并注意5的确是质数。

现在这是您要考虑的问题。这种方法如何保证您发现的每个新因素都是素数?

注意:但是请记住,虽然上述方法在处理由相对较小的素数组成的大数时应该会加快处理速度,但是如果您进行测试(例如,素数很大

答案 2 :(得分:0)

是的,共识是因素列表[1..n]。当您最小化因素列表而又不失去有效性时,它可以加快速度。我使用一个有效的限制因素列表。假定所有质数都是十分之四(即[11,13,17,19,21,23,27,29,31 ...])。以下从11(指定)开始,因为从1开始将包括1和9。7之后的所有素数都以1,3,7或9结尾。 此列表消除了偶数和5s。以下也消除了3s。

no2s3s5s = scanl (\b a -> a + b) 11 $ cycle [2,4,2,4,6,2,6,4]

因子列表的长度不必超过sqrt n,所以...

fa n=[x|x<-2:3:5:7:(take (floor.sqrt.fromIntegral$n+2) no2s3s5s),mod n x == 0]

fa列出了因素,其中很多是主要因素

fa 909090 OR fa 121
[2,3,5,7,13,37,91,259,481,3367] AND [11] recpectively

要从列表中删除非素数

pr n = (null $ fa n) || (fa n == [n])

[ d | d<-2:3:5:7:(take 200 no2s3s5s), pr d ]

生成素数列表,但速度很慢,因为所有使用因子列表或除数的此类函数都是如此。