C语言判断给定的数是否为质数的函数
质数定义
质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
判断一个数是否为质数的方法
- 对于质数p,从2开始一直到p-1,每个数都试除一下,如果有整除的情况,则说明p不是质数,否则说明p是质数。
- 实际上,可以不用一直到p-1,到p的平方根就可以,如果用2到p的平方根之间的所有整数去试除,均无法整除,则p为质数。这样可以减少试除的次数,提高判断效率!!!
- 模运算mod,即求余数运算,操作符%,如果 n % i == 0 则说明n除以i的余数为0,即n能被i整除,i是n的因数,i大于1,则n不是质数。
- 编码时,判断给定的整数n,从i=2开始,直到ii <= n(ii==n,则i是n的平方根),i每次增加一,循环判断 n%i == 0,如果成立返回0,说明n不是质数,如果循环顺利结束,则说明n是质数,返回1。
代码如下:
/* filename: prime.c */
#include <stdio.h>
/* compile : gcc prime.c -o prime
run : ./prime */
/* first version */
int
is_prime (int n)
{
if (n < 2) return 0;
if (n == 2) return 1;
for (int i = 2; i*i <= n; i++)
if (n % i == 0) return 0;
return 1;
}
/* get prime frome 1 to n */
void
get_prime (int n)
{
printf ("Prime from 1 to %d :\n", n);
for (int i = 0; i < n; i++)
//if (1 == is_prime (i)) printf ("%d ", i);
if (is_prime(i)) printf ("%d ", i);
printf ("\n");
}
/**/
int
main (int argc, char *argv[])
{
get_prime (100);
return 0;
}
/* --(:-O-:)-- */
编译运行,结果如下:
songvm@ubuntu:~/works/xdn$ gcc prime.c -o prime
songvm@ubuntu:~/works/xdn$ ./prime
Prime from 1 to 100 :
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
is_prime函数第二个版本
- 以上的效果可以!改造一下,可以判断大一点儿的整数,参数改为无符号长整型!!!
- 将函数is_prime重写,提高效率,分成四种情况:
- 条件一:0和1不是质数!!!
- 条件二:2是质数!!!
- 条件三:能被2整除的数(偶数)不是质数,2除外(条件二)!!!
- 条件四:能被大于等于3的奇数整除的数不是质数!!!
- 不满足上述四个条件则是质数!!!
- 依次输出1 - 100,1 - 1000,1 - 10000,1 - 100000区间的质数数量
代码如下:
/* filename: prime.c */
#include <stdio.h>
/* compile : gcc prime.c -o prime
run : ./prime */
/**/
typedef unsigned long ulong;
/* second version */
ulong
is_prime (ulong n)
{
if (n < 2) return 0; //0,1 not a prime
if (n == 2) return 1; //2 is a prime
if (n % 2 == 0) return 0; //Even numbers not a prime
for (ulong i = 3; i*i <= n; i = i + 2)
if (n % i == 0) return 0; //Divided by odd numbers not a prime
return 1;
}
/* test, get prime count 1 to 100000 */
void
test_get_prime (void)
{
int count = 0;
for (ulong i = 1; i < 100000; i++)
{
if (is_prime(i)) count++;
if (i == 100)
printf ("1 - 100 : %d\n", count);
else if (i == 1000)
printf ("1 - 1000 : %d\n", count);
else if (i == 10000)
printf ("1 - 10000 : %d\n", count);
}
printf ("1 - 100000 : %d\n", count);
}
/**/
int
main (int argc, char *argv[])
{
test_get_prime ();
return 0;
}
/* --(:-O-:)-- */
编译运行,结果如下:
songvm@ubuntu:~/works/xdn/woo$ gcc prime.c -o prime
songvm@ubuntu:~/works/xdn/woo$ ./prime
1 - 100 : 25
1 - 1000 : 168
1 - 10000 : 1229
1 - 100000 : 9592
测试大的整数区间
- 再测试一下,找出从0xFFFFFF01到0xFFFFFFFF之间的质数。(16进制很有用呀!)
- 用16进制写长整型数,判断一个大一点儿的整数区间!!!
代码如下:
/* filename: prime.c */
#include <stdio.h>
/* compile : gcc prime.c -o prime
run : ./prime */
/**/
typedef unsigned long ulong;
/* second version */
ulong
is_prime (ulong n)
{
if (n < 2) return 0; //0,1 not a prime
if (n == 2) return 1; //2 is a prime
if (n % 2 == 0) return 0; //Even numbers not a prime
for (ulong i = 3; i*i <= n; i = i + 2)
if (n % i == 0) return 0; //Divided by odd numbers not a prime
return 1;
}
/* test, get prime from 0xFFFFFF01 to 0xFFFFFFFF */
void
test_get_prime (void)
{
int count = 0;
ulong uf = 0xFFFFFF01;
ulong ut = 0xFFFFFFFF;
printf ("Prime from %lu to %lu :\n", uf, ut);
for (ulong i = uf; i <= ut; i = i + 2)
{
if (is_prime(i))
{
count++;
printf ("%d, %lX, %lu\n", count, i, i);
}
}
}
/**/
int
main (int argc, char *argv[])
{
test_get_prime ();
return 0;
}
/* --(:-O-:)-- */
编译运行,结果如下:
songvm@ubuntu:~/works/xdn$ gcc prime.c -o prime
songvm@ubuntu:~/works/xdn$ ./prime
Prime from 4294967041 to 4294967295 :
1, FFFFFF2F, 4294967087
2, FFFFFF47, 4294967111
3, FFFFFF67, 4294967143
4, FFFFFF79, 4294967161
5, FFFFFF95, 4294967189
6, FFFFFF9D, 4294967197
7, FFFFFFBF, 4294967231
8, FFFFFFEF, 4294967279
9, FFFFFFFB, 4294967291
- test_get_prime函数中,for循环每次增加2,只测试奇数,偶数不用测试,因为它不是质数!!!
- 在254个数中间找到了9个质数,是不是数越大,质数的分布就越稀薄了?!
用第一个版本验证
- 数太大将整型改为无符号长整型!!!
代码如下:
/* filename: prime.c */
#include <stdio.h>
/* compile : gcc prime.c -o prime
run : ./prime */
/**/
typedef unsigned long ulong;
/* first version */
int
is_prime (ulong n)
{
if (n < 2) return 0;
if (n == 2) return 1;
for (ulong i = 2; i*i <= n; i++)
if (n % i == 0) return 0;
return 1;
}
/* test, get prime from 0xFFFFFF01 to 0xFFFFFFFF */
void
test_get_prime (void)
{
int count = 0;
ulong uf = 0xFFFFFF01;
ulong ut = 0xFFFFFFFF;
printf ("Prime from %lu to %lu :\n", uf, ut);
for (ulong i = uf; i <= ut; i = i + 2)
{
if (is_prime(i))
{
count++;
printf ("%d, %lX, %lu\n", count, i, i);
}
}
}
/**/
int
main (int argc, char *argv[])
{
test_get_prime ();
return 0;
}
/* --(:-O-:)-- */
编译运行,结果一致
songvm@ubuntu:~/works/xdn/woo$ ./prime
Prime from 4294967041 to 4294967295 :
1, FFFFFF2F, 4294967087
2, FFFFFF47, 4294967111
3, FFFFFF67, 4294967143
4, FFFFFF79, 4294967161
5, FFFFFF95, 4294967189
6, FFFFFF9D, 4294967197
7, FFFFFFBF, 4294967231
8, FFFFFFEF, 4294967279
9, FFFFFFFB, 4294967291
最后测试一下,统计1到10亿之间共有多少个质数
代码如下:
/* filename: prime.c */
#include <stdio.h>
/* compile : gcc prime.c -o prime
run : ./prime */
/**/
typedef unsigned long ulong;
/* second version */
ulong
is_prime (ulong n)
{
if (n < 2) return 0; //0,1 not a prime
if (n == 2) return 1; //2 is a prime
if (n % 2 == 0) return 0; //Even numbers not a prime
for (ulong i = 3; i*i <= n; i = i + 2)
if (n % i == 0) return 0; //Divided by odd numbers not a prime
return 1;
}
/* test, get prime count 1 to 1000000000 */
void
test_get_prime (void)
{
int count = 0;
for (ulong i = 1; i < 1000000000; i++)
{
if (is_prime(i)) count++;
}
printf ("1 - 1000000000 : %d\n", count);
}
/**/
int
main (int argc, char *argv[])
{
test_get_prime ();
return 0;
}
/* --(:-O-:)-- */
编译运行,结果如下:
songvm@ubuntu:~/works/xdn/woo$ gcc prime.c -o prime
songvm@ubuntu:~/works/xdn/woo$ ./prime
1 - 1000000000 : 50847534
这个程序在我的虚拟机上运行了一个半小时可能还多,因为我用ps -all看到下面结果后,去了一次洗手间,回来再用ps -all才发现看不到prime进程了 😦
0 R 1000 8770 8227 99 80 0 - 1129 - pts/1 01:23:05 prime
- 50847534,这个结果和网上搜索到的结果是一致的,谢天谢地!!!
- 还有更快的方法,就是筛选法,下一步研究一下!同时也核对一下这个数。