騷操作,利用正則表示式判斷素數!!!
利用正則判斷素數
判斷素數有很多方法, 比如定義法,費馬小定理,米勒-拉賓素性檢驗,Solovay-Strassen素性判定等。
一、定義法
這種方法利用素數定義來判斷素數。
素數又叫質數,質數是指在大於1的自然數中,除了1和它本身以外,不能被其他自然數整除的數。最小的質數是2,它也是唯一的偶數質數,最前面的質數依次排列為:2、3、5、7、11、13、17、19、23、29、31等。
static boolean isPrime(int n) {
if (n <= 1)
return false;
else if (n == 2)
return true;
else if (n % 2 == 0) return false;
for (int i = 3; i <= Math.sqrt(n); i += 2) {
if (n % i == 0) return false;
}
return true;
}
二、費馬小定理
費馬小定理(Fermat’s little theorem)是數論中的一個重要定理,在1636年提出。如果p是一個質數對於任意a,
1
<
a
<
n
−
1
1 < a < n-1
a
n
−
1
≡
1
(
m
o
d
n
)
a^{n-1}\equiv1(mod\ n)
an−1≡1(modn) 或者
a
n
−
1
a^{n-1}
an−1 %
n
=
1
n=1
n=1
static int power(int a, int n, int p) {
int res = 1;
a = a % p;
while (n > 0) {
if ((n & 1) == 1) res = (res * a) % p;
n = n >> 1; // n = n/2
a = (a * a) % p;
}
return res;
}
static boolean isPrime(int n, int k) {
if (n <= 1 || n == 4) return false;
if (n <= 3) return true;
while (k > 0) {
int a = 2 + (int) (Math.random() % (n - 4));
if (power(a, n - 1, n) != 1) return false;
k--;
}
return true;
}
三、利用正則判斷素數
public static void main(String[] args) {
System.err.println(prime(0));
// false
System.err.println(prime(1));
// true
System.err.println(prime(2));
// true
System.err.println(prime(3));
// true
System.err.println(prime(5));
// false
System.err.println(prime(8));
// true
System.err.println(prime(13));
// false
System.err.println(prime(14));
// false
System.err.println(prime(15));
}
public static boolean prime(int n) {
return !new String(new char[n]).matches(".?|(..+?)\\1+");
}
改演算法的精髓在 !new String(new char[n]).matches(".?|(..+?)\\1+");
這行程式碼。
該函式首先生成n個字元,並嘗試檢視該字串是否匹配".?|(..+?)\\1+"
。如果n是素數,則matches函式會返回false,然後!
再將結果反轉。
表示式的第一部分.?
是確保1不是素數。因為n等於1或者0的話,String的長度為1或者0,那麼.?
會匹配上,經過!
返回false
。最重要的地方在表示式的第二部分括號括起來的部分。(..+?)
以非貪婪模式方式匹配至少兩個字元,然後\\1
反向引用(..+?)
匹配到的部分,再利用+
匹配至少一次。
根據定義,素數是一個大於1的自然數,除了1和它本身沒有正因子。這意味著如果
a
=
n
×
m
a=n\times m
a=n×m,那麼a不是素數。
n
×
m
n\times m
n×m可以進一步解釋n個字元重複m次”,這便是正則表示式的原理。使用(..+?)
匹配n個字元長度,然後使用\\1
重複m次。