更新后的哥德巴赫猜想(位运算)

德巴赫猜想:一个不小于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;
}


转载于:https://www.cnblogs.com/youdiaodaxue16/p/9122079.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值