我已经在C ++中编写了一个Eratosthenes算法的筛子,它适用于我测试过的较小数字。但是,当我使用大数字,即2 000 000作为上限时,程序开始给出错误的答案。谁能澄清为什么?
感谢您的帮助。
#include <iostream>
#include <time.h>
using namespace std;
int main() {
clock_t a, b;
a = clock();
int n = 0, k = 2000000; // n = Sum of primes, k = Upper limit
bool r[k - 2]; // r = All numbers below k and above 1 (if true, it has been marked as a non-prime)
for(int i = 0; i < k - 2; i++) // Check all numbers
if(!r[i]) { // If it hasn't been marked as a non-prime yet ...
n += i + 2; // Add the prime to the total sum (+2 because of the shift - index 0 is 2, index 1 is 3, etc.)
for(int j = 2 * i + 2; j < k - 2; j += i + 2) // Go through all multiples of the prime under the limit
r[j] = true; // Mark the multiple as a non-prime
}
b = clock();
cout << "Final Result: " << n << endl;
cout << b - a << "ms runtime achieved." << endl;
return 0;
}
编辑:我刚刚进行了一些调试,发现它可以在400左右的极限下运行。然而,在500,它是关闭的 - 它应该是21536,但是是21499
编辑2:啊,我发现了两个错误,似乎已经解决了这个问题。
第一个是由其他人回答的,并且n是溢出的 - 当它成为一个很长的数据类型时,它已经开始工作了。
第二个,也就是值得称赞的错误,是r中的布尔值必须初始化。在检查素数之前运行循环以使它们全部为假,得到了正确的答案。有谁知道为什么会这样?
答案 0 :(得分:2)
你只是得到一个整数溢出。 C ++类型int
具有有限的范围(在32位系统上通常从 - (2 ^ 32)/ 2到2 ^ 32/2 - 1,这通常的最大值是2147483647(特定的最大值您的设置可以通过#include <limits>
标头并评估std::numeric_limits<int>::max()
找到。即使k小于最大值,您的代码迟早会导致表达式n += i + 2
溢出或int j = 2 * i + 2
。
您必须选择更好(读取:更合适)的类型,例如unsigned
,它不支持负数,因此可以表示两倍于int
的数字。您也可以尝试unsigned long
甚至unsigned long long
。
另请注意,可变长度数组(VLA;那就是bool r[k - 2]
)不是标准C ++。您可能希望使用std::vector
代替。您也没有将数组初始化为false
(std::vector
会自动执行此操作),这也可能是问题所在,尤其是如果您说即使在k = 500时它也不起作用。
在C ++中,您还应该使用<ctime>
而不是<time.h>
(然后使用clock_t
和and
clock()are defined in the
std namespace, but since you are
namespace std`,这对你没什么影响),但这或多或少是风格问题。
我在“代码存档”中找到了一个工作示例。虽然它不是基于您的,但您可能会发现它很有用:
#include <vector>
#include <iostream>
int main()
{
typedef std::vector<bool> marked_t;
typedef marked_t::size_type number_t; // The type used for indexing marked_t.
const number_t max = 500;
static const number_t iDif = 2; // Account for the numbers 1 and 2.
marked_t marked(max - iDif);
number_t i = iDif;
while (i*i <= max) {
while (marked[i - iDif] == true)
++i;
for (number_t fac = iDif; i * fac < max; ++fac)
marked[i * fac - iDif] = true;
++i;
}
for (marked_t::size_type i = 0; i < marked.size(); ++i) {
if (!marked[i])
std::cout << i + iDif << ',';
}
}