第一步是认识到将其分割成任意大小的块是微不足道的;而且您不需要为每个数字使用数组(或位域)。例如,如果您只关心100000到110000之间的数字,则可以将所有可被3整除的数字标记为“非质数”,方法是"
for( index = 3 * (100000+3-1)/3; index < 110000; index += 3) {
"。以下是更灵活的示例:
for( value = 2; value < sqrt( block_end_value-1); value++ ) {
for( index = value * (block_state_value+value -1)/value; index < block_end_value; index += value ) {
mark_not_prime(index - block_state_value);
}
}
第二步是认识到你不需要关心每个数字(上面的
for( value = 2; value < sqrt( block_end_value-1); value++)
是低效的)。例如,如果你已经标记了可被2整除的数字为“非质数”,那么就没有必要关心能否被4、6或8整除;如果你已经标记了可被3整除的数字为“非质数”,那么就没有必要关心能否被6、9或12整除;......基本上,你只想测试一个数字是否能被另一个质数整除。这意味着要在100000到110000范围内找到质数,你首先要在0到sqrt(110000)范围内找到质数;如果你想在0到sqrt(110000)范围内找到质数,你需要在0到sqrt(sqrt(110000))范围内找到质数;......
第三步是意识到可以通过复制重复模式来加速。您可以创建一个2位模式(表示“可被2整除”),并将这两位复制到每个位置。同样,您可以创建一个6位模式(表示“可被2或3整除”),并将这6位复制到每个位置。同样,您可以创建一个39916800位模式(表示“可被2、3、4、5、6、7、8、9、10和11整除”),并将该39916800位模式复制到每个位置。当然,您也可以预先生成模式并将其存储在程序代码中。
第四步是意识到2的倍数太过简单,不用存储它们,这样可以减半所有表格和模式(以及任何存储/预生成的模式)的内存消耗。
通过结合以上第三步和第四步,表示“可被2、3、4、5、6、7、8、9、10和11整除”的预生成模式将花费19958400比特,约为2.38 MiB。独立使用此模式的第一部分也可用于查找从1到第一个大于11的质数(在本例中为1至13的数字)。
第五步是认识到如果你已经有了一个模式,你可以使用它来找到“
N =下一个“未标记”的质数
”,将现有的模式复制N次,然后将N的倍数标记为“非质数”;最终得到一个更大的模式。例如;如果你有一个表示“可被2、3、4、5、6、7、8、9、10和11整除”的模式,你会跳过12(因为根据现有模式它不是质数);将该模式复制13次,然后将可被13整除的数字标记为“非质数”,最终得到一个表示“可被2、3、4、5、6、7、8、9、10、11、12和13整除”的模式。
第六步是意识到一旦您拥有足够大的模式覆盖您所需的范围,您可以填补缺失的除数而无需复制。例如,如果您只想在1到6227020800的范围内得到质数,则可以采用代表“可被2、3、4、5、6、7、8、9、10、11、12和13整除”的模式,然后将在14到6227020800范围内可被质数整除的数字标记为“非质数”。
通过结合上述所有内容,如果你想在1000000000到11000000000的范围内找到质数,则需要首先在1到sqrt(11000000000)的范围内查找质数;为此,您需要复制预生成的模式并扩展它,直到获得足够大的表格来表示1到sqrt(11000000000)范围内的质数;然后复制该扩展模式并填充缺失的数字以生成表示1到sqrt(11000000000)范围内的质数的表格;接着创建1000000000到11000000000范围内的质数表,并通过从“扩展预生成的模式”中复制数据来初始化内存,然后使用1到sqrt(11000000000)范围内的质数表来查找尚未合并到“扩展预生成的模式”中的质数,以查找仍需标记为“非质数”的数字,这些数字是生成1000000000到11000000000范围内数字表所需的。