先来验证一下哥德巴赫猜想,请看代码;
因为哥德巴赫猜想是:任一大于5的偶数,都可以分解为两个质数之和,
所以我们先验证一下1000以内的质数都是什么。编写testGoldBach.c程序。
执行结果如下所示:再编写,任意偶数都可以等于哪些质数之和
执行结果如下
再编写 ,输入一个范围,检测这个范围内的偶数是否都符合哥德巴赫猜想
执行结果如下:
可见 百位数的验证是正确的,接下来,就该正式进入话题了
用刚才的代码,验证万位的数,代码及执行结果如下:(为了更好的表明时间复杂度,将代码进行了更改)
我测试了6位数,两分钟结果也没出来,所以没有截图,有兴趣的话可以自己进行实验,
从时间复杂度可得知,上面的代码,时间复杂度太高了,下面将代码进行优化:
其实,上述代码,优化程度最大的地方是 isPrime()函数,isPrime()函数里,for循环的条件没必要为i < num,因为,假如判断一个数10000,这样要判断近10000次,然而,从5001到9999之间,不会存在一个数可以被10000整除,;再思考,10000 / 3,那么,3333到4999之间就没必要考虑了,如果10000 / 4,那么,2501到 3332之间就没有必要考虑了,以此类…而且如果我们检测过了2,那就没有必要再检测5000了,所以,对于10000,我们只需要从2检测到100就够了,也就是检测到根号10000就够了,
所以,代码做以下的优化:执行结果如下:
再验证一下:
我们可以对比优化前后的差距,其实代码还可以优化!!!
为了方便,我们先建立一个头文件,如下:
可以发现,再头文件中设置了两个宏,用的是位运算,这样可以加快运算速度,为了进一步提高运算速度,我们还是要对isPrime()函数进行优化,因为两个数作比较比较麻烦,所以我们用查表来代替直接比较,先定义一个数组,令质数为1,非质数为0,
但是有一个问题,0或者1只需要一个位就能表示,不需要用一个字节来表示,用一个字节表示的话,利用率是12.5%,浪费的厉害,所以改用一个位来表示0或1:
现在就有一个疑问,那么该定义多少个质数才合适?其实,用筛选法可以解决这个方法,可以网上搜一下这个方法,简述一下:2为质数,那么2的倍数就不用管了,3是质数,那么3的质数就不用管了,4不是质数,直接不用管,5是质数,5的倍数就不用管了…以此类推,
我们还是要先补充一下头文件,(补充的头文件内容,注释都有解释)
重新定义,并对isPrime()进行修改:
因为calloc()函数申请的空间会自动赋值为0,所以,我们把质数赋值为0,非质数赋值为1,这样可以减少改动的次数(0和1只是为了区别质数与非质数,这样做只是为了简化代码)如下图所示:这样所有代码就完成了,我们来验证一下结果:
这就是结果,对比前面优化了一点点代码的结果,这里5位的数才用了0.005秒,再来验证一下7位数:
只用了0.518秒, 最后来测试一下8位数,看看时间:
只用了7.050秒!!!!!!
完整代码,请看github:https://github.com/xiami-maker/-/tree/master
感谢指导教师:铁血教主
本次测验如上所述,如有不足或者可以改进的地方,请指教~