前言
前面写过两篇关于素数相关的博客,一篇是关于如何判断素数,一篇是关于如何求取指定范围的素数集。参考百度百科,分解质因数就是是把一个合数分解成若干个质因数的乘积形式。可以看到分解质因数其实和质数还是关系的,因此萌发了写这篇博客的念头。
基本分解质因数法
该方法的基本思想就是找到分解后的质数,通过求余迭代实现。我在网上找到一个介绍该算法思路比较通俗的博文,传送门:分解质因数算法。代码如下:
public static int[] factor(int n){
if(n < 0){
throw new IllegalArgumentException("N must be a non negative integer.");
}
if(n < 4){
return new int[]{n};
}
int factorNums = (int)(Math.log(Integer.highestOneBit(n)) / Math.log(2));
int[] factors = new int[factorNums];
int factorCount = 0;
for(int i = 2; i <= (int) Math.sqrt(n); i++){
if(n % i == 0){
factors[factorCount++] = i;
n /= i;
i = 1;
}
}
factors[factorCount++] = n;
return Arrays.copyOf(factors, factorCount);
}
原理比较简单,具体参照我给的传送门。我主要说说那个factorNums值,它是个估计质因子数量的值。我们知道2是最小质数,因此如果一个数的质因子全是2,那么所有比它小的数,它们的质因子数一定会比它少。并且如果一个数据n在和之间,那么它的质因数的长度绝对小于等于m,反证法很好证明,这里就不多说了。如果我要确定n的质因子数量,只需要计算出m值即可。首先求出这个数二进制的最高位的值p,即代码Integer.highestOneBit(n),然后通过计算出m,但是Java没有2为底的对数,只能用对数公式计算了。
素数分解质因数法
根据分解质因数的定义,可以知道,我们得到的结果全是素数,假设我们将√n前面所有素数全取出来,具体细节参考如何求取指定范围的素数集,然后一个一个求余,这样也能将所有质因子求出来。代码如下:
public static int[] factor(int n){
if(n < 0){
throw new IllegalArgumentException("N must be a non negative integer.");
}
if(n < 4){
return new int[]{n};
}
int factorNums = (int)(Math.log(Integer.highestOneBit(n)) / Math.log(2));
int[] factors = new int[factorNums];
int factorCount = 0;
int[] primes = primes((int) Math.sqrt(n));
int primeNums = primes.length;
for(int i = 0; i < primeNums; ){
int prime = primes[i];
if(n % prime == 0){
factors[factorCount++] = prime;
n /= prime;
}else{
i++;
}
}
if(n != 1){ // N is a prime number.
factors[factorCount++] = n;
}
factors = Arrays.copyOf(factors, factorCount);
Arrays.sort(factors); // These prime numbers in array are in disorder.
return factors;
}
Matlab2014a版分解质因数法
接下来介绍的是Matlab2014a版的factor方法,主要是给大家多提供点思路。
public static int[] factor(int n){
if(n < 0){
throw new IllegalArgumentException("N must be a non negative integer.");
}
if(n < 4){
return new int[]{n};
}
int factorNums = (int)(Math.log(Integer.highestOneBit(n)) / Math.log(2));
int[] factors = new int[factorNums];
int factorCount = 0;
int[] primes = primes((int) Math.sqrt(n));
while(true){
int primeProd = 1;
for(int prime : primes){
if(n % prime == 0){
factors[factorCount++] = prime;
primeProd *= prime;
}
}
if(primeProd == 1){ // Now, n is a prime number.
factors[factorCount++] = n;
break;
}
if((n = n / primeProd) <= 1){
break;
}
}
factors = Arrays.copyOf(factors, factorCount);
Arrays.sort(factors); // These prime numbers in array are in disorder.
return factors;
}
其实,第二种方法和这种方法原理相同,但看起来,第二种方法比这种方法效率要高。在Java平台上,可能的确如此,但是在Matlab平台下,这就不一定了,毕竟两者优化的侧重点不同。
后记
这两天终于把素数相关的东西学了点,虽然学的非常浅,连皮毛都不到,但代码写起来还是很舒服。一想到此时刻正是11月10日23:58分,别人的购物快乐,我却什么都没有,哎!!!