搜索
查看: 4550|回复: 11
打印 上一主题 下一主题

判断2147483647这个质数,用了近10秒,吐血。。。

[复制链接]
跳转到指定楼层
楼主
发表于 2013-10-22 21:53:28 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 start1980 于 2013-10-22 21:54 编辑

啊哈C第1页介绍的神奇素数,今天学完了整本书,回过头用代码判断了一下这个质数,结果用了近10秒,书上说用1秒,难道我的电脑是386吗??什么原因?
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main()
  4. {
  5.         int a,b,f;
  6.     a=2147483647;
  7.     f=1;
  8.     for(b=2;b<=a-1;b++)
  9.     {
  10.                 if(a%b==0)
  11.                         f=0;
  12.     }
  13.     if(f==0)
  14.                 printf("这是一个合数!");
  15.     else
  16.                 printf("这是一个质数!");
  17.         system("pause");
  18.         return 0;
  19. }
复制代码
沙发
发表于 2013-10-22 23:03:58 | 只看该作者
试除到sqrt(a)就可以了
板凳
 楼主| 发表于 2013-10-23 14:04:38 | 只看该作者
sqrt这个函数没学过,如果用这个函数的话,这个程序该如何写?
地板
发表于 2013-10-23 14:26:31 | 只看该作者
.....我会告诉你我的用了30秒吗!
5#
发表于 2013-10-23 14:58:01 | 只看该作者
首先说明,2147483647是一般环境下的INT_MAX,下面代码用的都是INT_MAX以免打错

第一个很慢的版本,也是最平庸的做法,试除到 n/2
  1. #include <stdio.h>
  2. #include <limits.h>

  3. int main()
  4. {
  5.   int is_prime = 1;
  6.   int div = 2;
  7.   int upper = INT_MAX/2;
  8.   for(; div <= upper; ++div)
  9.     if(INT_MAX % div == 0){
  10.       is_prime = 0;
  11.       break;
  12.   }
  13.   if(is_prime)
  14.     printf("%d is a prime\n", INT_MAX);
  15.   else
  16.     printf("%d is not a prime\n", INT_MAX);
  17.   return 0;
  18. }
复制代码
用POSIX time在我的机器上测定,耗时6.39s

第二个版本,首先把所有偶数都筛掉
  1. #include <stdio.h>
  2. #include <limits.h>

  3. int main()
  4. {
  5.   int is_prime = 1;
  6.   int div;

  7.   if(INT_MAX % 2 == 0)
  8.     is_prime = 0;
  9.   else
  10.     for(div = 3; div <= INT_MAX/2; div+=2)
  11.       if(INT_MAX % div == 0){
  12.         is_prime = 0;
  13.         break;
  14.       }
  15.   if(is_prime)
  16.     printf("%d is a prime\n", INT_MAX);
  17.   else
  18.     printf("%d is not a prime\n", INT_MAX);

  19.   return 0;
  20. }
复制代码
不出意料,时间减少了一半,3.20s

第三个版本,也就是6n±1筛法,把2和3的倍数都筛掉,只用检验6n±1
  1. #include <stdio.h>
  2. #include <limits.h>

  3. int main()
  4. {
  5.   int is_prime = 1;
  6.   int div;
  7.   if(INT_MAX % 2 == 0 || INT_MAX % 3 == 0)
  8.     is_prime = 0;
  9.   else
  10.     for(div = 6; div <= INT_MAX/2+1; div += 6)
  11.       if(INT_MAX % (div-1) == 0 || INT_MAX % (div+1) == 0){
  12.         is_prime = 0;
  13.         break;
  14.       }

  15.   if(is_prime)
  16.     printf("%d is a prime", INT_MAX);
  17.   else
  18.     printf("%d is not a prime", INT_MAX);
  19.   return 0;
  20. }
复制代码
时间减少了大约1/3, 2.12s

最后,试除到sqrt(n), 并且筛掉所有偶数
  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <limits.h>

  4. int main()
  5. {
  6.   int is_prime = 1;
  7.   int upper = sqrt(INT_MAX);
  8.   if(INT_MAX % 2 == 0)
  9.     is_prime = 0;
  10.   else{
  11.     int div;
  12.     for(div = 3; div <= upper; div+=2)
  13.         if(INT_MAX % div == 0){
  14.             is_prime = 0;
  15.             break;
  16.         }
  17.   }
  18.   if(is_prime)
  19.     printf("%d is a prime\n", INT_MAX);
  20.   else
  21.     printf("%d is not a prime\n", INT_MAX);
  22.   return 0;
  23. }
复制代码
时间测定是0.00s,就不继续往下写了……
6#
发表于 2013-10-23 18:21:37 | 只看该作者
超棒的技巧!!!
7#
 楼主| 发表于 2013-10-24 09:32:20 | 只看该作者
rosynirvana真是牛,原来可以有这么多算法,收藏了,非常感谢!
8#
发表于 2013-10-29 09:08:25 | 只看该作者
我告诉你我的废电脑用了2.5分钟又怎么样······
9#
发表于 2013-10-30 23:02:45 | 只看该作者
大神哦!!!!!
10#
发表于 2014-11-22 17:23:48 | 只看该作者
大神啊!!!!!!!
11#
发表于 2014-12-2 10:55:44 | 只看该作者
好厉害!!!!!!!
12#
发表于 2015-6-25 22:08:45 | 只看该作者
原来程序可以这样写
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

广播台
特别关注
快速回复 返回顶部 返回列表