看了风过无痕的贴子,得知程序可以进一步优化,num/3其实是一个数最大因子的极限(最大因子不会超过num/3),也就是说,假设循环中找到因子我们也不break,我们会把这个数的所有因子都找出来。
但其实只要找到一个因子,就能说明这个数字不是素数了,所以我们需要的是那个最小因子的极限(最小因子最大不会超过多少)。如果验证到这个最小因子的极限都没有找到因子,就说明这个数不存在最小因子(当然是除了1和它本身)。存在因子即一定能找到最小(对于一个确切的合数,因子数量必然有限,这个楼上有分析),如果找不到最小因子,就说明没有因子,也就说明这个数是素数。
那这个最小因子最大不会超过多少呢?假设合数m=a*b*c*d.........何时最小的因子最大?自然是因子数目越小越好,所以最好的情况是m只能分成2个质数因子a*b。这两个数里最小的那个最大不会超过多少呢?自然是a和b相等的时候,这个最小的因子获得了它可能取得的最大值(根号m)。如果a和b不相等,必然一个大于(根号m),一个小于(根号m),此时最小因子是小于(根号m)的。
楼上说了这么多废话,只是告诉我们,验证因子的时候只需要验证到(int)(Math.sqrt(num))即可。验证方式自然还是采取奇数偶数分别对待,偶数直接判断,奇数从3开始验证。代码- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace ConsoleApplication2
- {
- class Program
- {
- static void Main(string[] args)
- {
- string flag = "";
- do
- {
- int j = 3;
- Console.WriteLine("请输入一个正整数,我们将判断是否为素数");
- int num = Convert.ToInt32(Console.ReadLine());
- if (num == 2)
- Console.WriteLine("2是素数");
- else if (num % 2 == 0)
- Console.WriteLine("{0}不是素数,可以被2整除", num);
- else
- {
- for (; j <= (int)Math.Sqrt(num); j += 2)
- {
- if (num % j == 0)
- break;
- }
- //当num是大于等于9素数时,循环至少进行一次,
- //若(int)Math.Sqrt(num)是偶数,那么最后一次验证的j==(int)Math.Sqrt(num)-1
- //循环结束时,j又加2,所以最终j==(int)Math.Sqrt(num)+1
- //若(int)Math.Sqrt(num)是奇数,那么最后一次验证的j==(int)Math.Sqrt(num)
- //循环结束时,j又加2,所以最终j==(int)Math.Sqrt(num)+2
- //
- //当num是小于9的非2素数时(3,5,7),循环不进行,j的终值也就是初值3。
- //若num=3,(int)Math.Sqrt(num)=1,j==(int)Math.Sqrt(num)+2
- //若num=5或者7,(int)Math.Sqrt(num)=2,j==(int)Math.Sqrt(num)+1
- //
- //所以得出,这种判断对于一切非2素数均有效(其实2也是有效的,只不过最开始判断了)。
- if (j == ((int)Math.Sqrt(num)) + 1 || j == ((int)Math.Sqrt(num)) + 2)
- Console.WriteLine("{0}是素数", num);
- else
- Console.WriteLine("{0}不是素数,可以被{1}整除", num, j); //人性化一点给出不是素数的证据
- }
- Console.WriteLine("输入y退出,其他继续");
- flag = Console.ReadLine();
- } while (flag != "y" );
- Console.ReadKey();
- }
- }
- }
复制代码 这里说下程序中一大段注释下面那个判断,
if (j == ((int)Math.Sqrt(num)) + 1 || j == ((int)Math.Sqrt(num)) + 2)
这是一种比较精确的写法,但是也有可以笼统写,效果看起来会比较简洁
if (j > ((int)Math.Sqrt(num)))
因为如果num是合数(大于等于9的),循环肯定通过break跳出,j的取值情况必然满足循环判断条件:if (j <= ((int)Math.Sqrt(num)))。除此之外,我们可以不必细致去分析当num是质数的时候,两种情况j的取值究竟都是多少。
|