更新后的哥德巴赫猜想(位运算)
哥德巴赫猜想:一个不小于6的偶数,总能分解成两个质数之和。
#include(stdio.h)
#include(math.h)
boolean isPrime(int num);
boolean isGoldbachConjecture(int arrange);
boolean GoldbachConjecture(int arrange){
boolean isGoldbachRight;
boolean found;
int num;
int i;
for(num = 6,isGoldbachRight =1;isGoldbachRight&&num<=arrange;num+=2){
//例如:6=3+3;
//24=3+(24-3);
//24=5+(24-5);
//24=7+(24-7);
//24=9+(24-9);
//这是下面这个循环的手工过程。
for(i=3,found=-1;!found&&i<=num/2;i+=2){
if(isPrime(i)&&isPrime(num-i)){
found=1;
}
}
if(!found){
isGoldbachRight = -1;
printf("%d\n",num);
}
}
return isGoldbachRight;
}
boolean isPrime(int num){ //判断是否是质数
int i;
int maxNum = (int)(sqrt(num));
if(num>2&&num%2 == 0){
return -1;
}
for(i=3;i<maxNum&&num%i;i+=2){
}
return i>maxNum;
}
int main(){
int num;
printf("请输入范围:");
scanf("%d",&num);
if(GoldbachConjecture(num)==-1){
printf("哥德巴赫猜想错了!");
}esle{
printf("哥德巴赫猜想从6到%d是正确的\n",num);
}
return 0;
}
但是这个程序对于7位数以上的数据,会非常耗时!!!
所以有了更加高效的解决手段:利用数组的位运算解决:
首先:将相当大的数,全部存储到数组中;或者说,有一个数组,里面有n个数,这n个数就是
我们要处理的数据;其实,如果定义一个有n个数的数组,那么,其下标就是0到n-1!而其值,我们要求为0或者1,且0表示非质数,1表示质数(相反亦可)例如:数组名numSet.
0 0 1 1 0 1 0 1 0 0 0
0 1 2 3 4 5 6 7 8 9 10
对于上述数组的处理可以这样操作:return numSet[num];
而对于数组的赋值,可以这样来:int numSet[1000] = {0};
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <malloc.h>
#include "./include/mec.h"
u8 *set = NULL; //在宏中定义u8类型为unsigned char(用了宏,为避免错误发生)
boolean isPrime(int num);
boolean GoldbachConjecture(int arrange);
void setPrime(int arrange);
void setPrime(int arrange) { //查找质数
int i = 3;
int j;
int maxNum = (int) sqrt(arrange);
set = (u8 *) calloc(sizeof(u8), (arrange + 7) >> 3);
for (j = 4; j < arrange; j += 2) {
SET_BYTE(set[j >> 3], j & 7); //置0操作,相当于set[j] = 1;
}
while (i <= maxNum) {
if (0 == GET_BYTE(set[i >> 3], i & 7)) { //置1操作,相当于if(0 == set[i])
for (j = i*i; j < arrange; j += (i << 1)) { //左移n位,相当于原数*2^n,再去掉前面多出来的那些位!所以j += (i << 1)相当于j += i + 2;
SET_BYTE(set[j >> 3], j & 7); //置0操作,相当于set[j] = 1;
}
}
i += 2;
}
}
boolean GoldbachConjecture(int arrange) {
boolean isGoldbachRight;
boolean found;
int num;
int i;
for (num = 6, isGoldbachRight = TRUE; isGoldbachRight && num <= arrange; num += 2) {
for (i = 3, found = FALSE; !found && i <= num/2; i += 2) {
if (isPrime(i) && isPrime(num-i)) {
// printf("%d = %d + %d\n", num, i, num-i);
found = TRUE;
}
}
if (!found) {
isGoldbachRight = FALSE;
printf("%d\n", num);
}
}
return isGoldbachRight;
}
boolean isPrime(int num) {
return 0 == GET_BYTE(set[num >> 3], num & 7);
}
int main() {
int num;
boolean ok = TRUE;
clock_t start; //返回当前进程创建到现在经过的时钟周期数。
long mid; ////clock_t ,long是一样的。
clock_t end;
clock_t deltaA;
long deltaB;
printf("输入范围:");
scanf("%d", &num);
start = clock();
setPrime(num);
mid = clock();
ok = GoldbachConjecture(num);
end = clock();
deltaA = mid - start;
deltaB = end - mid;
printf("%d.%03d, %d.%03d\n", (int) (deltaA / 1000000), (int) (deltaA % 1000000 / 1000),
(int) (deltaB / 1000000), (int) (deltaB % 1000000 / 1000));
if (FALSE == ok) {
printf("哥德巴赫猜想错了!\n");
} else {
printf("哥德巴赫猜想在6到%d之间正确\n", num);
}
free(set);
return 0;
}