问题陈述是在时间范围内找到低于20亿的素数&lt; 20秒我遵循以下方法。将数字n除以数字k的列表(k <sqrt(n)) - 花费20秒划分……
首先要做的是确保您在启用优化的情况下进行编译。 c ++标准库模板类在未经优化的代码中往往表现很差,因为它们会生成大量函数调用。优化器内联大多数函数调用,这使得它们更便宜。
std::list 是一个链表。在您想要随机插入或删除元素(即不是从末尾)的情况下,它非常有用。
std::list
对于仅附加到列表末尾的情况 std::list 有以下问题:
int
一个 std::vector 将解决上述所有问题,因为它的内存是连续的,并且迭代它基本上只是递增数组索引的情况。你需要确保你打电话 reserve 在你的矢量开头有一个足够大的值,以便附加到向量不会导致整个数组被复制到一个新的更大的数组。
std::vector
reserve
比上面更大的优化是使用 Eratosthenes的筛子 计算你的素数。生成此灯需要随机删除(取决于您的确切实现) std::list 可能表现得比 std::vector 虽然在这种情况下即使是开销 std::list 可能不会超过其成本。
/* check_prime__list: time taken No of divisions No of primes 10M: 0.873 seconds 286144936 664579 20M: 2.169 seconds 721544444 1270607 */ 2B: projected time: at least 16 minutes but likely much more (*) /* check_prime__nums: time taken No of divisions No of primes 10M: 4.650 seconds 1746210131 664579 20M: 12.585 seconds 4677014576 1270607 */ 2B: projected time: at least 3 hours but likely much more (*)
我还改变了与之对应的分割数量的类型 long int 因为它围绕数据类型限制。所以他们 可以 一直在曲解 那 。
long int
但 的 运行时间 强> 没有受到影响。挂钟是挂钟。
最可能的解释似乎是OP的一个草率测试,错误地在每个测试用例中使用了不同的值。
(*)时间投影是由 经验增长的顺序 分析:
100**1.32 * 2.169 / 60 = 15.8 100**1.45 * 12.585 / 3600 = 2.8
对于列表算法,在给定的大小范围内测量的经验增长顺序明显更好, ñ 1.32 的 与...相对 ñ 1.45 的 所有数字的测试。这完全是从理论上的复杂性来预期的,因为素数比所有数字都要少 ñ ,因数 登录 ,总的复杂性 上 1.5 / log n) 的 与 上 1.5 ) 的 。任何实现差异也不太可能超过实际的算法优势。