C 为什么这段代码会进入无限循环

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

下面的函数检查整数是否为素数

我正在运行一个从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%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