素发生器优化

时间:2009-08-18 13:27:16

标签: php math optimization

我开始探索Project Euler。和其他许多人一样,我认为我需要制作一个素数发生器。问题是:PHP不喜欢大数字。如果我使用标准Sieve of Eratosthenes function,并将限制设置为200万,它将崩溃。它不喜欢创建那种大小的数组。可以理解的。

所以现在我正在尝试优化它。我找到的一种方法是,不是创建一个包含200万个变量的数组,而是只需要100万个(只有奇数可以是素数)。但是现在它崩溃了,因为它超过了最大执行时间......

function getPrimes($limit) {
$count = 0;
for ($i = 3; $i < $limit; $i += 2) {
    $primes[$count++] = $i;
}

for ($n = 3; $n < $limit; $n += 2) {
    //array will be half the size of $limit
    for ($i = 1; $i < $limit/2; $i++) {
        if ($primes[$i] % $n === 0 && $primes[$i] !== $n) {
            $primes[$i] = 0;
        }
    }
}

return $primes;
}

该功能有效,但正如我所说,它有点慢......有什么建议吗?

我发现让它快一点的一件事就是切换循环。

foreach ($primes as $value) {
    //$limitSq is the sqrt of the limit, as that is as high as I have to go
    for ($n = 3; $n = $limitSq; $n += 2) {
        if ($value !== $n && $value % $n === 0) {
            $primes[$count] = 0;
            $n = $limitSq; //breaking the inner loop
        }
    }
    $count++;
}

另外设置时间和内存限制(感谢Greg),我终于设法得到了答案。 phjew。

5 个答案:

答案 0 :(得分:4)

不太了解算法:

  1. 您每次围绕$ i循环重新计算$limit/2
  2. 您的if语句将按顺序进行评估,因此请考虑(或测试)首先测试$primes[$i] !== $n是否会更快。
  3. 旁注,您可以使用set_time_limit()为其提供更长的运行时间,并使用

    为其提供更多内存
    ini_set('memory_limit', '128M');
    

    假设您的设置允许此操作,当然 - 在共享主机上您可能会受到限制。

答案 1 :(得分:3)

来自Algorithmist's proposed solution

  

这是对标准的修改   Eratosthenes的筛子。这将是   效率极低,用得太多了   很多记忆和时间,运行   标准筛一直到n。   但是,没有复合数小于   或等于n将有一个因素   大于sqrt {n},   所以我们只需知道所有素数   达到这个限制,这不是更大   比31622(平方根10 ^ 9)。这个   用筛子完成。的然后,   对于每个查询,我们只筛选   给出的范围,使用我们的   预先计算的素数表   消除综合数字

此问题也出现在UVA和Sphere的在线评委中。 Here's how it's enunciated on Sphere.

答案 2 :(得分:2)

您可以使用位字段存储筛子。也就是说,除了你把布尔值打包成一个大整数之外,它与一系列布尔值大致相同。例如,如果你有8位整数,你将每整数存储8位(布尔值),这将进一步减少你的空间需求。

此外,使用位字段可以使用位掩码执行筛选操作。例如,如果您的筛子保留所有数字(不仅仅是奇数),您可以构造一个b01010101的位掩码,然后您可以对阵列中的每个元素。对于三个,您可以使用三个整数作为掩码:b00100100 b10010010 b01001001。

最后,您无需检查低于$n的数字,实际上您无需检查小于$n*$n-1的数字。

答案 3 :(得分:0)

一旦你知道这个数字不是素数,我就会退出回路。我不知道php,但你需要一个语句,如C语言中的中断或Perl中的最后一个语句。

如果那个不可用,我会设置一个标志并用它来退出inter循环作为继续interloop的条件。这样可以加快执行速度,因为如果它不是素数,你不会检查$ limit / 2项。

答案 4 :(得分:0)

如果你想要速度,不要在这个上使用PHP:P

不,说真的,我真的很喜欢PHP而且它是一种很酷的语言,但它根本不适合这种算法