C#找梅森素數
梅森素數是由梅森數而來。
所謂梅森數,是指形如2p-1的一類數,其中指數p是素數,常記爲Mp 。如果梅森數是素數,就稱爲梅森素數。比如2^2-1=3,2^3-1=7,2^5-1=31,2^7-1=127,指數P也是素數,同時也用M2,M3,M5,M7表示。
用因式分解法可以證明,若2n-1是素數,則指數n也是素數;反之,當n是素數時,2n-1(即Mp)卻未必是素數。前幾個較小的梅森數大都是素數,然而梅森數越大,梅森素數也就越難出現。
2008年8月23日,美國加州大學洛杉磯分校的計算機專家史密斯終於發現超過1000萬位的梅森素數 。 它有12978189位數,如果用普通字號將這個巨數連續打印下來,它的長度可超過50公里!這一成就被美國的《時代》雜誌評爲 “2008年度50項最佳發明” 之一,排名在第29位。
2013年1月,美國中央密蘇里大學數學教授柯蒂斯·庫珀領導的研究小組發現了第48個梅森素數 。[12] 這一發現被英國《新科學家》週刊評爲當年自然科學十大突破之一。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConAppPrimeNumber2
{
//Mersenne prime number
//梅森素數的公式2^P-1(用2的冪次方減1表示,其中P也是一個素數)
//比如2^2-1=3,2^3-1=7,2^5-1=31,2^7-1=127,指數P也是素數
//同時也用M2,M3,M5,M7表示
class Program
{
static void Main(string[] args)
{
System.Diagnostics.Stopwatch s = new Stopwatch();
PrimeNumber.testPower();
System.Console.WriteLine();
s.Reset();
s.Start();
PrimeNumber.Find5();
s.Stop();
System.Console.WriteLine("Watch Time:{0}m, {1}s, {2}ms", s.Elapsed.Minutes, s.Elapsed.Seconds, s.ElapsedMilliseconds);
System.Console.WriteLine();
s.Reset();
s.Start();
PrimeNumber.Find6();
s.Stop();
System.Console.WriteLine("Watch Time:{0}m, {1}s, {2}ms", s.Elapsed.Minutes, s.Elapsed.Seconds, s.ElapsedMilliseconds);
}
}
public class PrimeNumber
{
static int n = 100000; //查找100(n=100)以內的素數
//static int n = 1000000;
static bool IsPN = false; //找到素數就設置爲true
static int count = 0; //計數器
//找梅森素數,方式一(從質數中去找)//性能低,找到第五位M17(耗時10分鐘)
//經過優化代碼後,找到第六位M19(耗時30秒)//M31 -> 2ms //終於找天第九位M61(耗時2分10秒)
public static void Find5()
{
IsPN = false;
//System.Console.Write(2 + "\t"); //素數2還是在這裏輸出
//count = 1;
count = 0;
int MaxMP = 63; //不能設置成64,因爲0~63其實就已經是64位了,long最大就是64位,2^64已經歸零了,就好比bit=0~255,2^8-1
long MaxMPN = PowerOfTwo(MaxMP) - 1;
//int temp = 2;//從指數2開始,p=2
for (long i = 1; i < long.MaxValue; i += 2)
{
for (long j = 3; j < i; j += 2) //此處的i=3也不會被執行,因爲j<i,不滿足條件,就算j<=i,那麼i%j也會把3=i認爲是合數
{
if (i % j == 0)
{
IsPN = false;
break;
}
if (j * j > i)
//if(j> Math.Sqrt(i))
{
IsPN = true;
break;
}
}
if (i == 2 || i == 3) IsPN = true; //2不會被執行,因爲前面的循環是(i=1;i+=2)
//if (i == 3) IsPN = true; //素數3因爲要參與是否是梅森素數的計算,所以放在這裏
if (IsPN)
{
//System.Console.Write(i + "\t");
//count++;
for (int p = 2; p <= MaxMP; p++)
//for (int p = temp; p <= MaxMP; p++)
{
//if (p != 2 && p % 2 == 0) continue; //M62執行不了,死循環,設置成61時看不出問題來
//if (p != 3 && p % 3 == 0) continue; //M63同樣
long MP = PowerOfTwo(p) - 1;
if (i < MP)
{
i = MP - 2;
break;
}
if (i == MP)
{
count++;
System.Console.Write("[No.{0} M{1}] ", count, p);
System.Console.Write("Mersenne prime number: 2^{0}-1={1}" + "\n", p, i);
if (p == MaxMP) return; //如果已經找到就退出,後面的i循環就不需要再執行(比如設置MaxMP爲32,比較完M32,則i=M32~long.MaxValue就不執行)
//temp = p + 1; //前面的就不比較,已經測試,性能並無提升
//i = PowerOfTwo(p + 1) - 1 - 2; //不減2會漏掉 M3 => 2^3-1=7 //M61 -> 2.23m
i = MP; //前面的就不比較 //M61 -> 3.10m
break;
}
}
}
else
{
if (i > MaxMPN) return;//如果已經把最大的2^MaxMP-1比較完,就退出程序。
}
}
System.Console.WriteLine("Count: {0}", count);
}
//找梅森素數,方式二(從梅森數中去找梅森素數)//性能高,能夠找到第八位M31(耗時15秒)//第九位找到了,M61 -> 23s
//梅森數:滿足條件2^P-1,但這個數不一定是素數,比如2^4-1=15
//梅森素數:比如2^3-1=7
public static void Find6()
{
IsPN = false;
count = 0;
//已知梅森指數MP:P=2, 3, 5, 7, 13, 17, 19, 31, 61, 89, 107, 127, ...目前發現最大的P=57,885,161,是第48位,其長度有17,425,170位
//已知梅森素數:3, 7, 31, 127, 8191, 131071, 524287, 2147483647, ...
//因爲long最大就是64位,所以只能計算到64位
for (int p = 2; p <= 64; p++)
{
long MP = (PowerOfTwo(p) - 1);
long MPSqrt = p % 2 == 0 ? PowerOfTwo(p / 2) : PowerOfTwo((p + 1) / 2);
//long MPSqrt =(long)Math.Sqrt(MP);//使用.NET內置對象數學函數求值(開平方根)
for (long j = 3; j < (MP); j += 2)
{
//System.Console.Title = j.ToString();//注意指數P小於20可以使用,否則容易死機
if (MP % j == 0)
{
IsPN = false;
System.Console.Write("Is not Mersenne prime number:2^{0}-1={1}" + "\n", p, MP);//滿足條件2^P-1,但不是梅森素數
break;
}
//if (j * j > (MP))
if (j > MPSqrt)
{
IsPN = true;
break;
}
}
if (p == 2) IsPN = true;//當指數p爲2時,將得到素數3,因爲要參與是否是梅森素數的計算,所以在這裏加上這個條件
if (IsPN)
{
count++;
System.Console.Write("[No.{2} M{3}] Mersenne prime number: 2^{0}-1={1}" + "\n", p, MP, count, p);//梅森素數
}
}
System.Console.WriteLine("Count: {0}", count);
}
//鎖定梅森素數的範圍
public static long PowerOfTwo(int p)
{
long num = 2;
//if (p == 0) return 1;
//if (p == 1) return 2;
switch (p)
{
case 0:
num = 1;
break;
case 1:
num = 2;
break;
default:
num = 2;
break;
}
for (int i = 1; i < p; i++)
{
num *= 2;
}
return num;
}
public static void testPower()
{
for (int i = 0; i <= 64; i++)
{
System.Console.Write("2^{0}={1}" + "\t", i, PowerOfTwo(i));
}
}
}
}
寫這篇文章時梅森素數還只發現48個,今天整理了下代碼,才知道現在已經發現第49個了。
2016年1月7日,庫珀又發現第49個梅森素數 274207281-1。這個超大素數有22338618位,是目前已知的最大素數。
版權所有,轉載請註明文章出處 http://blog/csdn.net/cadenzasolo