C 为什么这段代码会进入无限循环
下面的函数检查整数是否为素数 我正在运行一个从3到2147483647(+ve long int限制)的for循环 但是这个代码挂起了,不知道为什么C 为什么这段代码会进入无限循环,c,long-integer,C,Long Integer,下面的函数检查整数是否为素数 我正在运行一个从3到2147483647(+ve long int限制)的for循环 但是这个代码挂起了,不知道为什么 #include<time.h> #include<stdio.h> int isPrime1(long t) { long i; if(t==1) return 0; if(t%2==0) return 0; for(i=3;i<t/2;i+=2) { if(t
#include<time.h>
#include<stdio.h>
int isPrime1(long t)
{
long i;
if(t==1) return 0;
if(t%2==0) return 0;
for(i=3;i<t/2;i+=2)
{
if(t%i==0) return 0;
}
return 1;
}
int main()
{
long i=0;
time_t s,e;
s = time(NULL);
for(i=3; i<2147483647; i++)
{
isPrime1(i);
}
e = time(NULL);
printf("\n\t Time : %ld secs", e - s );
return 0;
}
#包括
#包括
int isPrime1(长t)
{
龙我;
如果(t==1)返回0;
如果(t%2==0)返回0;
对于(i=3;i它最终将终止,但需要一段时间,如果您在内联isPrime1
函数时查看循环,您会发现:
for(i=3; i<2147483647; i++)
for(j=3;j<i/2;j+=2)
对于(i=3;i这里试试这个,看看它是否真的是一个无限循环
int main()
{
long i=0;
time_t s,e;
s = time(NULL);
for(i=3; i<2147483647; i++)
{
isPrime1(i);
//calculate the time execution for each loop
e = time(NULL);
printf("\n\t Time for loop %d: %ld secs", i, e - s );
}
return 0;
}
intmain()
{
长i=0;
时间s,e;
s=时间(空);
对于(i=3;i它取决于系统和编译器。在Linux上,使用GCC 4.7.2并使用GCC-O2 vishaid.c-o vishaid进行编译时,程序立即返回,编译器通过删除它们来优化对isPrime1
的所有调用(我用gcc-O2-S-fverbose asm
检查生成的汇编程序代码,然后main
甚至不调用isPrime1
)。gcc是正确的:因为isPrime1
没有副作用,并且它的结果没有被使用,所以它的调用可以被删除。然后for
循环的主体是空的,因此也可以被优化
要吸取的教训是,在对优化的二进制文件进行基准测试时,最好在代码中有一些真正的副作用
此外,算术告诉我们,如果某个i
的除数不小于其平方根,则它是素数。因此,更好的代码:
int isPrime1(long t) {
long i;
double r = sqrt((double)t);
long m = (long)r;
if(t==1) return 0;
if(t%2==0) return 0;
for(i=3;i <= m;i +=2)
if(t%i==0) return 0;
return 1;
}
大约4分钟后,它仍在打印很多行,包括
#6819840: 119566439
#6823936: 119642749
#6828032: 119719177
#6832128: 119795597
我猜它需要几个小时才能完成。30分钟后,它还在吐(慢慢地)
实际上,这个程序需要4小时16分钟才能完成。最后的输出是
#105086976: 2147139749
#105091072: 2147227463
#105095168: 2147315671
#105099264: 2147402489
Time : 15387 secs
顺便说一句,这个程序仍然非常低效:来自bsdgames
软件包的primes
程序/usr/games/primes
的响应速度要快得多
% time /usr/games/primes 1 2147483647 | tail
2147483423
2147483477
2147483489
2147483497
2147483543
2147483549
2147483563
2147483579
2147483587
2147483629
/usr/games/primes 1 2147483647
10.96s user 0.26s system 99% cpu 11.257 total
它仍然打印了105097564行(大多数被tail
跳过)
如果你对素数生成感兴趣,读几本数学书(如果你对效率感兴趣,这仍然是一个研究课题;你仍然可以获得这方面的博士学位。)。从维基百科上的和页面开始
最重要的是,首先使用调试信息和所有警告编译程序(即Linux上的gcc-Wall-g
),并学习使用调试器(即Linux上的gdb
),然后可以中断调试过的程序(使用gdb
下的Ctrl-C
,然后让它继续执行cont
命令到gdb
)大约一分钟零两分钟后,然后观察主菜单中的i
计数器正在缓慢增加。可能还需要分析信息(使用-pg
选项选择gcc
,然后使用gprof
)。在编写复杂的算术代码时,阅读有关它们的优秀数学书籍是非常值得的(素性测试是一个非常复杂的主题,是大多数密码算法的核心).这是一种非常低效的测试素数的方法,这就是为什么它似乎挂起的原因。
在网络上搜索更有效的算法,比如Eratosthenes的筛子你确定它真的挂起了,不是执行起来需要很长时间吗?你确定它实际上被卡在一个循环中,而不是执行起来很长吗?我不认为它是一个无限循环。你只是有超过2147483647个循环,就这样。一点也不oo heavyMaybe这对你的电脑来说太多了,你有没有试过用一个更小更大的数字,比如for(i=3;在我看来,这件事的复杂性是n^2,因此2147483647可能在推动它。之所以发生这种情况,是因为他在本例中没有使用返回值,因为这是一个最小的示例。对于一个实际的程序,他可能对返回值感兴趣;)我知道这一点,但我想把原始海报吸引到一些关于优化和基准测试的有趣点。
#105086976: 2147139749
#105091072: 2147227463
#105095168: 2147315671
#105099264: 2147402489
Time : 15387 secs
% time /usr/games/primes 1 2147483647 | tail
2147483423
2147483477
2147483489
2147483497
2147483543
2147483549
2147483563
2147483579
2147483587
2147483629
/usr/games/primes 1 2147483647
10.96s user 0.26s system 99% cpu 11.257 total