给定数字n,检查它是否为质数。我们已经介绍和讨论了Set 1中用于素数测试的School方法。
原始性测试|第一组(介绍和学校方法)
在这篇文章中,讨论了费马方法。该方法是一种概率方法,基于Fermat的Little定理。
Fermat's Little Theorem:
If n is a prime number, then for every a, 1 < a < n-1,
an-1 ≡ 1 (mod n)
OR
an-1 % n = 1
Example: Since 5 is prime, 24 ≡ 1 (mod 5) [or 24%5 = 1],
34 ≡ 1 (mod 5) and 44 ≡ 1 (mod 5)
Since 7 is prime, 26 ≡ 1 (mod 7),
36 ≡ 1 (mod 7), 46 ≡ 1 (mod 7)
56 ≡ 1 (mod 7) and 66 ≡ 1 (mod 7)
Refer this for different proofs.
如果给定的数字是质数,则此方法始终返回true。如果给定的数字是合成数(或非素数),则它可能返回true或false,但是为合成数生成错误结果的可能性很低,并且可以通过执行更多迭代来降低。
下面是算法:
// Higher value of k indicates probability of correct
// results for composite inputs become higher. For prime
// inputs, result is always correct
1) Repeat following k times:
a) Pick a randomly in the range [2, n - 2]
b) If gcd(a, n) ≠ 1, then return false
c) If an-1 ≢ 1 (mod n), then return false
2) Return true [probably prime].
下面是上述算法的实现。该代码使用了模幂的幂函数
C++
// C++ program to find the smallest twin in given range
#include
using namespace std;
/* Iterative Function to calculate (a^n)%p in O(logy) */
int power(int a, unsigned int n, int p)
{
int res = 1; // Initialize result
a = a % p; // Update 'a' if 'a' >= p
while (n > 0)
{
// If n is odd, multiply 'a' with result
if (n & 1)
res = (res*a) % p;
// n must be even now
n = n>>1; // n = n/2
a = (a*a) % p;
}
return res;
}
/*Recursive function to calculate gcd of 2 numbers*/
int gcd(int a, int b)
{
if(a < b)
return gcd(b, a);
else if(a%b == 0)
return b;
else return gcd(b, a%b);
}
// If n is prime, then always returns true, If n is
// composite than returns false with high probability
// Higher value of k increases probability of correct
// result.
bool isPrime(unsigned int n, int k)
{
// Corner cases
if (n <= 1 || n == 4) return false;
if (n <= 3) return true;
// Try k times
while (k>0)
{
// Pick a random number in [2..n-2]
// Above corner cases make sure that n > 4
int a = 2 + rand()%(n-4);
// Checking if a and n are co-prime
if (gcd(n, a) != 1)
return false;
// Fermat's little theorem
if (power(a, n-1, n) != 1)
return false;
k--;
}
return true;
}
// Driver Program to test above function
int main()
{
int k = 3;
isPrime(11, k)? cout << " true\n": cout << " false\n";
isPrime(15, k)? cout << " true\n": cout << " false\n";
return 0;
}
Java
// Java program to find the
// smallest twin in given range
import java.io.*;
import java.math.*;
class GFG {
/* Iterative Function to calculate
// (a^n)%p in O(logy) */
static int power(int a,int n, int p)
{
// Initialize result
int res = 1;
// Update 'a' if 'a' >= p
a = a % p;
while (n > 0)
{
// If n is odd, multiply 'a' with result
if ((n & 1) == 1)
res = (res * a) % p;
// n must be even now
n = n >> 1; // n = n/2
a = (a * a) % p;
}
return res;
}
// If n is prime, then always returns true,
// If n is composite than returns false with
// high probability Higher value of k increases
// probability of correct result.
static boolean isPrime(int n, int k)
{
// Corner cases
if (n <= 1 || n == 4) return false;
if (n <= 3) return true;
// Try k times
while (k > 0)
{
// Pick a random number in [2..n-2]
// Above corner cases make sure that n > 4
int a = 2 + (int)(Math.random() % (n - 4));
// Fermat's little theorem
if (power(a, n - 1, n) != 1)
return false;
k--;
}
return true;
}
// Driver Program
public static void main(String args[])
{
int k = 3;
if(isPrime(11, k))
System.out.println(" true");
else
System.out.println(" false");
if(isPrime(15, k))
System.out.println(" true");
else
System.out.println(" false");
}
}
// This code is contributed by Nikita Tiwari.
Python3
# Python3 program to find the smallest
# twin in given range
import random
# Iterative Function to calculate
# (a^n)%p in O(logy)
def power(a, n, p):
# Initialize result
res = 1
# Update 'a' if 'a' >= p
a = a % p
while n > 0:
# If n is odd, multiply
# 'a' with result
if n % 2:
res = (res * a) % p
n = n - 1
else:
a = (a ** 2) % p
# n must be even now
n = n // 2
return res % p
# If n is prime, then always returns true,
# If n is composite than returns false with
# high probability Higher value of k increases
# probability of correct result
def isPrime(n, k):
# Corner cases
if n == 1 or n == 4:
return False
elif n == 2 or n == 3:
return True
# Try k times
else:
for i in range(k):
# Pick a random number
# in [2..n-2]
# Above corner cases make
# sure that n > 4
a = random.randint(2, n - 2)
# Fermat's little theorem
if power(a, n - 1, n) != 1:
return False
return True
# Driver code
k = 3
if isPrime(11, k):
print("true")
else:
print("false")
if isPrime(15, k):
print("true")
else:
print("false")
# This code is contributed by Aanchal Tiwari
C#
// C# program to find the
// smallest twin in given range
using System;
class GFG {
/* Iterative Function to calculate
// (a^n)%p in O(logy) */
static int power(int a,int n, int p)
{
// Initialize result
int res = 1;
// Update 'a' if 'a' >= p
a = a % p;
while (n > 0)
{
// If n is odd, multiply 'a' with result
if ((n & 1) == 1)
res = (res * a) % p;
// n must be even now
n = n >> 1; // n = n/2
a = (a * a) % p;
}
return res;
}
// If n is prime, then always returns true,
// If n is composite than returns false with
// high probability Higher value of k increases
// probability of correct result.
static bool isPrime(int n, int k)
{
// Corner cases
if (n <= 1 || n == 4) return false;
if (n <= 3) return true;
// Try k times
while (k > 0)
{
// Pick a random number in [2..n-2]
// Above corner cases make sure that n > 4
Random rand = new Random();
int a = 2 + (int)(rand.Next() % (n - 4));
// Fermat's little theorem
if (power(a, n - 1, n) != 1)
return false;
k--;
}
return true;
}
static void Main() {
int k = 3;
if(isPrime(11, k))
Console.WriteLine(" true");
else
Console.WriteLine(" false");
if(isPrime(15, k))
Console.WriteLine(" true");
else
Console.WriteLine(" false");
}
}
// This code is contributed by divyesh072019
PHP
= p
$a = $a % $p;
while ($n > 0)
{
// If n is odd, multiply
// 'a' with result
if ($n & 1)
$res = ($res * $a) % $p;
// n must be even now
$n = $n >> 1; // n = n/2
$a = ($a * $a) % $p;
}
return $res;
}
// If n is prime, then always
// returns true, If n is
// composite than returns
// false with high probability
// Higher value of k increases
// probability of correct
// result.
function isPrime($n, $k)
{
// Corner cases
if ($n <= 1 || $n == 4)
return false;
if ($n <= 3)
return true;
// Try k times
while ($k > 0)
{
// Pick a random number
// in [2..n-2]
// Above corner cases
// make sure that n > 4
$a = 2 + rand() % ($n - 4);
// Fermat's little theorem
if (power($a, $n-1, $n) != 1)
return false;
$k--;
}
return true;
}
// Driver Code
$k = 3;
$res = isPrime(11, $k) ? " true\n": " false\n";
echo($res);
$res = isPrime(15, $k) ? " true\n": " false\n";
echo($res);
// This code is contributed by Ajit.
?>
输出:
true
false
该解决方案的时间复杂度为O(k Log n)。请注意,幂函数需要O(Log n)时间。
请注意,即使我们增加迭代次数(较高的k),上述方法也可能会失败。存在一些具有以下性质的复合数字:a
我们很快将讨论更多的原始性测试方法。