关于埃拉托斯特尼筛法(Sieve of Eratosthenes)及其C++实现的问题

雨夜独行的人 2014-06-27 08:07:31
小弟这几天在做有关埃拉托斯特尼筛法的C++习题,在查阅了许多资料后,我写下了如下代码:
int main()
{
//向量元素值若为1,则元素序数为质数;向量元素若为0,则元素序数不是质数。
cout << "Please enter the upper limit: ";
int n,i,multiple,k;
cin >> n;
vector<int>primes;
for (i = 0; i < n + 1; ++i)
primes[i] = 1;
primes[0] = 0; //0,1都不是质数
primes[1] = 0;
for (i = 2; i < n + 1;++i)
{
if (primes[i]==1)
{
for (multiple=2;i*multiple<=sqrt(n);++multiple)
primes[i*multiple] = 0;
}
}
for (k = 2; k < n + 1;++k)
{
if (primes[k] == 1)
cout << k << endl;
}
}

我的目的是输入正整数n,输出所有小于n的质数。代码编译没有问题,但是运行时出现了错误:

看样子好像是向量范围出错了,但是我不明白具体的错误原因。请大家指教!
关于埃拉托斯特尼筛法,我主要参考了:
维基百科:https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
算法百科:http://www.algorithmist.com/index.php/Prime_Sieve_of_Eratosthenes
和YouTube上的一个讲解视频:https://www.youtube.com/watch?v=eKp56OLhoQs(请大家自备云梯……)
谢谢大家了!请大家多多指教!
...全文
451 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
雨夜独行的人 2014-06-28
  • 打赏
  • 举报
回复
引用 8 楼 brookmill 的回复:
我明白了,平方根应该在这里: for (i = 2; i <= sqrt(n);++i) 当然代码不能这么写,每次循环调用一次sqrt效率太低,应该 int s = sqrt(n); for (i = 2; i <= s;++i)
如果n是整型?sqrt(n)也是整型吗?
brookmill 2014-06-28
  • 打赏
  • 举报
回复
我明白了,平方根应该在这里: for (i = 2; i <= sqrt(n);++i) 当然代码不能这么写,每次循环调用一次sqrt效率太低,应该 int s = sqrt(n); for (i = 2; i <= s;++i)
brookmill 2014-06-28
  • 打赏
  • 举报
回复
引用 5 楼 xacbeyond 的回复:
按照算法原意,应该用n,但是根据参考资料,用sqrt(n)可以对算法进行优化,也可以证明两者是等效的。但在我的程序中,若用n,输出结果就是对的,若用sqrt(n)则不对……为什么呢?想不明白……
用sqrt优化是有可能的,因为可以减少很多循环次数,不过直接用sqrt(n)替换n肯定不对,比如n=100,平方根是10,那比10大的不就全被当成质数了。 楼主再好好研究一下算法吧。
雨夜独行的人 2014-06-28
  • 打赏
  • 举报
回复
引用 5 楼 xacbeyond 的回复:
[quote=引用 2 楼 brookmill 的回复:] 这个算法我不懂,不过我觉得楼主的理解可能有点问题。我做了以下两处改动之后,好像结果就对了: vector<int>primes; 改成 int *primes = new int [n+1]; // 当然最后要delete [] primes; for (multiple=2;i*multiple<=sqrt(n);++multiple) 改成 for (multiple=2;i*multiple<=(n);++multiple)
按照算法原意,应该用n,但是根据参考资料,用sqrt(n)可以对算法进行优化,也可以证明两者是等效的。但在我的程序中,若用n,输出结果就是对的,若用sqrt(n)则不对……为什么呢?想不明白……[/quote] 我明白了!是我自己理解错了!
雨夜独行的人 2014-06-28
  • 打赏
  • 举报
回复
引用 2 楼 brookmill 的回复:
这个算法我不懂,不过我觉得楼主的理解可能有点问题。我做了以下两处改动之后,好像结果就对了: vector<int>primes; 改成 int *primes = new int [n+1]; // 当然最后要delete [] primes; for (multiple=2;i*multiple<=sqrt(n);++multiple) 改成 for (multiple=2;i*multiple<=(n);++multiple)
按照算法原意,应该用n,但是根据参考资料,用sqrt(n)可以对算法进行优化,也可以证明两者是等效的。但在我的程序中,若用n,输出结果就是对的,若用sqrt(n)则不对……为什么呢?想不明白……
brookmill 2014-06-28
  • 打赏
  • 举报
回复
引用 9 楼 xacbeyond 的回复:
[quote=引用 8 楼 brookmill 的回复:] 我明白了,平方根应该在这里: for (i = 2; i <= sqrt(n);++i) 当然代码不能这么写,每次循环调用一次sqrt效率太低,应该 int s = sqrt(n); for (i = 2; i <= s;++i)
如果n是整型?sqrt(n)也是整型吗?[/quote] sqrt的返回值是double,这个查手册就能看到。c语言里面任何一个函数的返回值的类型都是固定的,和输入的参数是什么类型没关系。 int s = sqrt(n); 这里有个类型转换,和int s = 1.234是一样的过程,把浮点数转换成整数赋值给int变量。 i <= sqrt(n) 这里同样有类型转换,i要先转换成double再和sqrt的返回值做比较
雨夜独行的人 2014-06-28
  • 打赏
  • 举报
回复
引用 2 楼 brookmill 的回复:
这个算法我不懂,不过我觉得楼主的理解可能有点问题。我做了以下两处改动之后,好像结果就对了: vector<int>primes; 改成 int *primes = new int [n+1]; // 当然最后要delete [] primes; for (multiple=2;i*multiple<=sqrt(n);++multiple) 改成 for (multiple=2;i*multiple<=(n);++multiple)
引用 3 楼 brookmill 的回复:
要是楼主喜欢用vector,那就把 primes[i] = 1; 改成 primes.push_back(1); 这么改也能正确运行,但是接下来把vector当数组用,还是感觉有点怪。 关于楼主代码出错的原因:在primes的定义后面加一行: cout << "size=" << primes.size() << ",capacity=" << primes.capacity() << endl; 我这里显示capacity是0,也就是说这个vector的容量是0。然后primes[i]=1的时候就出错了,因为写到了它的容量允许的范围之外。而push_back发现容量不够的时候可以自动扩容。所以,既然用了vector,就尽量用它的成员函数,这样很多细节都可以由它们来负责处理。
我明白了!也加深了对向量的理解!谢谢!
brookmill 2014-06-27
  • 打赏
  • 举报
回复
要是楼主喜欢用vector,那就把 primes[i] = 1; 改成 primes.push_back(1); 这么改也能正确运行,但是接下来把vector当数组用,还是感觉有点怪。 关于楼主代码出错的原因:在primes的定义后面加一行: cout << "size=" << primes.size() << ",capacity=" << primes.capacity() << endl; 我这里显示capacity是0,也就是说这个vector的容量是0。然后primes[i]=1的时候就出错了,因为写到了它的容量允许的范围之外。而push_back发现容量不够的时候可以自动扩容。所以,既然用了vector,就尽量用它的成员函数,这样很多细节都可以由它们来负责处理。
brookmill 2014-06-27
  • 打赏
  • 举报
回复
这个算法我不懂,不过我觉得楼主的理解可能有点问题。我做了以下两处改动之后,好像结果就对了: vector<int>primes; 改成 int *primes = new int [n+1]; // 当然最后要delete [] primes; for (multiple=2;i*multiple<=sqrt(n);++multiple) 改成 for (multiple=2;i*multiple<=(n);++multiple)
brookmill 2014-06-27
  • 打赏
  • 举报
回复
为什么定义了vector又把它当数组用呢? 要是喜欢用vector就push_back,要是喜欢数组就int *primes=new int [n+1];

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧