我是C ++初学者;) 下面的代码有多好,可以找到2-1000之间的所有素数:
int i, j;
for (i=2; i<1000; i++) {
for (j=2; j<=(i/j); j++) {
if (! (i%j))
break;
if (j > (i/j))
cout << i << " is prime\n";
}
}
答案 0 :(得分:9)
当j = i时你停止。 第一个简单的优化是在j = sqrt(i)时停止(因为不存在大于其平方根的因子)。
更快的实现是例如sieve of eratosthenes。
编辑:代码看起来有点神秘,所以这是它的工作方式:
内部for的终止条件是i/j
,相当于j<i
(更清楚),因为当最终有j==i
时,我们会i/j==0
并且for会破裂。
下一次检查if(j>(i/j))
真的很讨厌。基本上它只是检查循环是否达到for的结束条件(因此我们有一个素数)或者如果我们达到显式中断(没有素数)。如果我们达到了结尾,那么j==i+1
(考虑一下)=&gt; i/j==0
=&gt;这是一个素数。如果我们中断,则意味着j
是i
的因子,但不仅仅是任何因素,实际上是最小的(因为我们在第一个j
处退出,除以{{1} }})!
由于i
是最小因素,因此另一个因素(或剩余因子的乘积,由j
给出)将大于或等于i/j
,因此进行测试。如果j
,我们会休息一下,j<=i/j
是j
的最小因素。
这是一些难以理解的代码!
答案 1 :(得分:0)
不是很好。在我的拙见中,缩进和间距是可怕的(没有冒犯)。为了清理一些:
int i, j;
for (i=2; i<1000; i++) {
for (j=2; i/j; j++) {
if (!(i % j))
break;
if (j > i/j)
cout << i << " is prime\n";
}
}
这揭示了一个错误:if (j > i/j) ...
需要位于内循环的外部才能实现。此外,我认为i/j
条件更令人困惑(更不用说速度慢),而不仅仅是说j < i
(甚至没有,因为一旦j
到达i
,{{ 1}}将是0)。在这些变化之后,我们有:
i % j
这很有效。然而,int i, j;
for (i=2; i<1000; i++) {
for (j=2; j < i; j++) {
if (!(i % j))
break;
}
if (j > i/j)
cout << i << " is prime\n";
}
混淆了我。我甚至无法弄清楚它为什么会起作用(我想如果我花了一段时间我可以搞清楚looking like this guy)。我会改为写j > i/j
。
您在此处实施的内容称为trial division。一个更好的算法是Eratosthenes的筛选,如另一个答案中所述。如果您实施了Eratosthenes筛选,还有几件事要检查:
答案 2 :(得分:0)
首先,你的代码既简短又正确,这在初学者时非常好。 ; - )
这就是我要改进代码的方法:
1)定义循环内的变量,这样它们就不会与其他东西混淆。我也会使绑定参数或常量。
#define MAX 1000
for(int i=2;i<MAX;i++){
for(int j=2;j<i/j;j++){
if(!(i%j)) break;
if(j>(i/j)) cout<<i<<" is prime\n";
}
}
2)我会使用Sieve of Eratosthenes,正如Joey Adams和Mau所建议的那样。注意我怎么不必写两次绑定,所以这两个用法总是相同的。
#define MAX 1000
bool prime[MAX];
memset(prime, sizeof(prime), true);
for(int i=4;i<MAX;i+=2) prime[i] = false;
prime[1] = false;
cout<<2<<" is prime\n";
for(int i=3;i*i<MAX;i+=2)
if (prime[i]) {
cout<<i<<" is prime\n";
for(int j=i*i;j<MAX;j+=i)
prime[j] = false;
}
界限也值得注意。 i*i<MAX
比j > i/j
快很多,而且您也不需要标记任何数字&lt;我*我,因为它们已经被标记,如果它们是复合的。最重要的是time complexity。
3)如果你真的想快速制作这个算法,你需要缓存优化它。我们的想法是首先找到所有素数&lt; sqrt(MAX)然后用它们来查找剩下的部分 素数。然后你可以使用相同的内存块来查找1024-2047的所有素数,比方说, 然后是2048-3071。这意味着所有内容都将保存在L1缓存中。我曾经通过在Eratosthenes的筛子上使用这种优化来测量~12次加速。
您也可以通过不存储偶数来减少空间使用量,这意味着 您不必经常执行计算以开始处理新块。
如果你是初学者,你应该暂时忘记缓存。
答案 3 :(得分:0)
我们在这里发布的一大堆文字的一个简单答案是:审判部门! 如果有人提到这项任务所依据的数学基础,我们将节省大量时间;)
答案 4 :(得分:0)
#include <stdio.h>
#define N 1000
int main()
{
bool primes[N];
for(int i = 0 ; i < N ; i++) primes[i] = false;
primes[2] = true;
for(int i = 3 ; i < N ; i+=2) { // Check only odd integers
bool isPrime = true;
for(int j = i/2 ; j > 2 ; j-=2) { // Check only from largest possible multiple of current number
if ( j%2 == 0 ) { j = j-1; } // Check only with previous odd divisors
if(!primes[j]) continue; // Check only with previous prime divisors
if ( i % j == 0 ) {
isPrime = false;
break;
}
}
primes[i] = isPrime;
}
return 0;
}
这是有效的代码。我还包括了之前海报中提到的许多优化。如果还有其他任何可以完成的优化,那么知道它将会提供信息。
答案 5 :(得分:0)
此功能可以更有效地查看数字是否为素数。
bool isprime(const unsigned long n)
{
if (n<2) return false;
if (n<4) return true;
if (n%2==0) return false;
if (n%3==0) return false;
unsigned long r = (unsigned long) sqrt(n);
r++;
for(unsigned long c=6; c<=r; c+=6)
{
if (n%(c-1)==0) return false;
if (n%(c+1)==0) return false;
}