1.试除法
检查2到√n之间的所有整数是否能整除n,时间复杂度O(✓n)
public static boolean isPrimeBasic(int n) {
if (n <= 1) return false;
if (n <= 3) return true; // 2和3是质数
if (n % 2 == 0 || n % 3 == 0) return false;
// 检查6k±1形式的除数
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
2.米勒拉宾,基于费马小定理的改进概率测试
对于大数快速判断
- 对于n < 2,047:k=1足够
- 对于n < 1,373,653:k=3
- 对于n < 9,080,191:k=31
- 一般应用k=40可达到极高准确率
时间复杂度:O(k log³n)
public static boolean isPrimeMillerRabin(long n, int k) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 == 0) return false;
// 将n-1表示为d*2^s
long d = n - 1;
int s = 0;
while (d % 2 == 0) {
d /= 2;
s++;
}
// 进行k轮测试
Random rand = new Random();
for (int i = 0; i < k; i++) {
long a = 2 + rand.nextLong() % (n - 3);
long x = modPow(a, d, n);
if (x == 1 || x == n - 1) continue;
boolean composite = true;
for (int j = 0; j < s - 1; j++) {
x = modPow(x, 2, n);
if (x == n - 1) {
composite = false;
break;
}
}
if (composite) return false;
}
return true;
}
private static long modPow(long a, long b, long mod) {
long result = 1;
a = a % mod;
while (b > 0) {
if (b % 2 == 1) {
result = (result * a) % mod;
}
a = (a * a) % mod;
b /= 2;
}
return result;
}
```js
源码中判断数字是否为质数的函数
BigInteger.isProbablePrime() 方法
import java.math.BigInteger;
public class PrimeCheck {
public static void main(String[] args) {
BigInteger number = new BigInteger("123456789");
// 使用 isProbablePrime 方法
boolean isPrime = number.isProbablePrime(100); // 确定性参数
System.out.println(number + " is prime? " + isPrime);
}
}
public boolean isProbablePrime(int certainty) {
if (certainty <= 0)
return true;
BigInteger w = this.abs();
if (w.equals(TWO))
return true;
if (!w.testBit(0) || w.equals(ONE))
return false;
return w.primeToCertainty(certainty, null);//certainty是指调用者愿意容忍的不确定性的度量:如果调用返回 true 此 BigInteger 为素数的概率超过 (1 - 1/2certainty)。该方法的执行时间与该参数的值成正比。
}
boolean primeToCertainty(int certainty, Random random) {
int rounds = 0;
int n = (Math.min(certainty, Integer.MAX_VALUE-1)+1)/2;
int sizeInBits = this.bitLength();
if (sizeInBits < 100) { //小于100位使用passesMillerRabin,确定性测试
rounds = 50;
rounds = n < rounds ? n : rounds;
return passesMillerRabin(rounds, random);
}
if (sizeInBits < 256) {
rounds = 27;
} else if (sizeInBits < 512) {
rounds = 15;
} else if (sizeInBits < 768) {
rounds = 8;
} else if (sizeInBits < 1024) {
rounds = 4;
} else {
rounds = 2;
}
rounds = n < rounds ? n : rounds;
//对于大整数,使用米勒-拉宾(Miller-Rabin)概率性测试和Lucas-Lehmer 测试等其他优化
return passesMillerRabin(rounds, random) && passesLucasLehmer();
}
实现原理:
- 对于小整数 (< 100位),使用确定性测试
- 对于大整数,使用米勒-拉宾(Miller-Rabin)概率性测试
- 结合了 Lucas-Lehmer 测试等其他优化
其他框架
- Apache Commons Math:
Primes类 - Google Guava:
LongMath.isPrime() - JScience: 提供更多数论算法
对于大多数应用场景,BigInteger.isProbablePrime() 已经足够且方便使用,是 Java 中判断质数的标准方法。