Java語言求解完美數(shù)代碼分析
1、概念
首先我們理解一下,什么叫做完美數(shù)?
問題描述:若一個自然數(shù),它所有的真因子(即除了自身以外的約數(shù))的和恰好等于它本身,這種數(shù)叫做完全數(shù)。簡稱“完數(shù)”
例如,
6=1+2+3
28=1+2+4+7+14
496=1+2+4+8+16+31+62+124+248
8128=1+2+4+8+16+32+64+127+254+508+1016+2032+4064
按照完數(shù)的定義,其實用程序求解完數(shù)并不是太難,先求解出這個數(shù)的所有真因子,然后相加,判斷是否等于它本身即可。但是,在這個數(shù)很小的時候,沒有什么問題,一旦這個數(shù)字超過一定的數(shù)值,那么問題就來了,程序的執(zhí)行效率就會變得低下。
我們優(yōu)化程序的算法邏輯,往往會考慮一個問題,怎么高效的利用計算機的特性?在它所定義的算法中,有沒有大量重復的無用功呢?沿著這樣的思路去考慮這個問題,我們會很快得到另外的一種解決方案。
2、說明
2.1分析
在這里,我們會不會很容易就想到,之前我們提到過的分解因式?是的,在解決完美數(shù)的時候,我們會用到分解因式。一般來說,求解完美數(shù)會經過三個步驟:
1.求出一定數(shù)目的質數(shù)表
2.利用質數(shù)表求指定數(shù)的因式分解
3.利用因式分解求所有真因數(shù)和,并檢查是否為完美數(shù)
2.2難點
初看之下,第一步和第二步是沒什么問題的,我們在前面的兩篇文章中已經探討過了,不清楚的同學可以查看。
重點是在第三步,如何求真因數(shù)和?方法很簡單,要先知道將所有真因數(shù)(有不清楚真因數(shù)概念的同學,去看看)和加上該數(shù)本身,會等于該數(shù)的兩倍(有些同學不知道,現(xiàn)在應該也知道了吧?),例如:
2 * 28 = 1 + 2 + 4 + 7 + 14 + 28
事實上,這段等式可以轉換為:(代碼輸入錯誤,我用截圖好了)

發(fā)現(xiàn)沒有?2和7都是因式分解得到的,那么,程序是不是有了簡化的地方?
2.3結論
只要求出因式分解,就可以利用循環(huán)求得等式后面的值,將該值除以2就是真因數(shù)和了;等式后面第一眼看時可能想到使用等比級數(shù)公式來解,不過會使用到次方運算,可以在進行讀取因式分解陣列時,同時計算出等式后面的值。
3、代碼
import java.util.ArrayList;
// 求解完美數(shù)
public class PerfectNumber {
// 傳入一個值,求解至少多少個完美數(shù)
public static int[] lessThan(int number) {
int[] primes = Prime.findPrimes(number);
ArrayList list = new ArrayList();
for(int i = 1; i <= number; i++) {
int[] factors = factor(primes, i);
if(i == fsum(factors))
list.add(new Integer(i));
}
int[] p = new int[list.size()];
Object[] objs = list.toArray();
for(int i = 0; i < p.length; i++) {
p[i] = ((Integer) objs[i]).intValue();
}
return p;
}
// 分解因式
private static int[] factor(int[] primes, int number) {
int[] frecord = new int[number];
int k = 0;
for(int i = 0; Math.pow(primes[i], 2) <= number;) {
if(number % primes[i] == 0) {
frecord[k] = primes[i];
k++;
number /= primes[i];
}
else
i++;
}
frecord[k] = number;
return frecord;
}
// 因式求和
private static int fsum(int[] farr) {
int i, r, s, q;
i = 0;
r = 1;
s = 1;
q = 1;
while(i < farr.length) {
do {
r *= farr[i];
q += r;
i++;
} while(i < farr.length - 1 &&
farr[i-1] == farr[i]);
s *= q;
r = 1;
q = 1;
}
return s / 2;
}
public static void main(String[] args) {
int[] pn = PerfectNumber.lessThan(1000);
for(int i = 0; i < pn.length; i++) {
System.out.print(pn[i] + " ");
}
System.out.println();
}
}
總結
以上就是本文關于Java語言求解完美數(shù)代碼分析的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關專題,如有不足之處,歡迎留言指出!
相關文章
mybatis注解之@Mapper和@MapperScan的使用
這篇文章主要介紹了mybatis注解之@Mapper和@MapperScan的使用,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
Spring注解@Autowired和@Resource的區(qū)別詳解
這篇文章主要介紹了Spring注解@Autowired和@Resource的區(qū)別詳解,@Autowired與@Resource都可以用來裝配bean,都可以寫在字段或setter方法上,@Resource是JDK提供的注解,默認按照名稱進行裝配,名稱可通過name屬性進行指定,需要的朋友可以參考下2023-12-12

