文章目錄
- 一、何謂完美數
- 二、尋找完美數
- (一)編程思路
- (二)編寫程序
- (三)運行程序
- 三、實戰小結
一、何謂完美數
- 完美數是一種特殊的自然數,它等于其所有正除數(不包括其本身)之和。完美數非常稀有,并且只存在于偶數中。第一個完美數是 6 6 6,其除數 1 1 1、 2 2 2、 3 3 3的和等于它本身。完美數與梅森素數緊密相關,如果 2 p ? 1 2^p - 1 2p?1是梅森素數,那么 2 p ? 1 ( 2 p ? 1 ) 2^{p-1}(2^p - 1) 2p?1(2p?1)就是完美數。古希臘數學家歐幾里得首次描述了完美數,但直到現代,已知的完美數仍然不多。尋找完美數是數論中一個古老而深奧的問題,至今仍在數學研究中占有一席之地。隨著數值的增大,發現新的完美數變得越來越困難,需要高效的算法和強大的計算資源。
- 6 = 1 + 2 + 3 6 = 1 + 2 + 3 6=1+2+3是最小的完美數,不僅如此, 6 = 1 × 2 × 3 6 = 1 \times 2 \times 3 6=1×2×3,《圣經》開篇《創世紀》里提到,上帝用6天的時間創造了世界(第 7 7 7天是休息日),而相信地心說的古希臘人認為,月亮圍繞地球旋轉所需的時間是 28 28 28天(即便在哥白尼的眼里,太陽系也恰好有 6 6 6顆行星)。古羅馬思想家圣奧古斯都在《上帝之城》中寫道:“ 6 6 6這個數本身就是完美的,并非因為上帝造物用了 6 6 6天;事實上,恰恰因為 6 6 6是完美的,所以上帝在 6 6 6天之內把一切事物都造好了。”
- 迄今為止( 2024 2024 2024年 7 7 7月 9 9 9日),人們只發現
51
個偶完美數,沒有人找到一個奇完美數,也沒有人能夠否定它的存在。不難證明,偶完美數均以數字 6 6 6或 8 8 8結尾。古希臘人曾猜測它們交替以 6 6 6和 8 8 8結尾,后來被證實是錯誤的。統計已有的完美數,以 8 8 8結尾的和以 6 6 6結尾的完美數分別是 19 19 19個和 32 32 32個,這個比值趨近于黃金分割比!有意思的是,黃金分割恰好也是畢達哥拉斯學派提出來的,只是他們當初沒想過其與完美數之間可能存在某種聯系。 - 所謂黃金分割比是指把一條線段分割成兩部分,使其中一部分與全長之比等于另一部分與這部分之比,其比值是 5 ? 1 2 ≈ 0.618 \displaystyle\frac{\sqrt{5}-1}{2}≈0.618 25??1?≈0.618…按此比例設計的造型特別美麗,被稱為黃金分割。這個數值不僅體現在諸如繪畫、雕塑、音樂、建筑等藝術領域,也在管理、工程設計等方面有重要的應用,在日常生活中的應用也比比皆是。
二、尋找完美數
(一)編程思路
-
理解完美數與梅森素數的關系:完美數是形式為 2 p ? 1 ( 2 p ? 1 ) 2^{p-1}(2^p - 1) 2p?1(2p?1)的數,其中 2 p ? 1 2^p - 1 2p?1必須是梅森素數。
-
實現Lucas-Lehmer素性測試:這是檢測梅森素數的一種有效方法。對于每個 p p p,計算序列直到 p ? 2 p-2 p?2項,如果最終結果為 0 0 0,則 2 p ? 1 2^p - 1 2p?1是素數。
-
尋找梅森素數:從 p = 2 p=2 p=2開始,對每個 p p p調用
lucasLehmerPrime
函數,檢查 2 p ? 1 2^p - 1 2p?1是否為素數。 -
計算并輸出完美數:一旦找到梅森素數,根據完美數的公式計算相應的完美數,并輸出結果。
-
設置搜索限制:程序將持續尋找并輸出完美數,直到找到大于預設限制的數為止。
-
優化與考慮:對于大數計算,使用
BigInteger
類處理可能的溢出問題。同時,考慮到計算量可能非常大,實際應用中可能需要進一步優化算法或使用并行計算。 -
代碼實現:將上述思路轉化為Java代碼,使用
BigInteger
類進行大數運算,實現完美數的搜索程序。
(二)編寫程序
- 在
net.huawei.number
包里創建PerfectNumberFinder
類
package net.huawei.number;import java.math.BigInteger;/*** 功能:完美數尋找器* 作者:華衛* 日期:2024年07月09日*/
public class PerfectNumberFinder {public static void main(String[] args) {// 設置尋找完美數的上限findPerfectNumbers(new BigInteger("1000000000000000000000000000000000000000000000000000000000000000000000000000"));}/*** 執行Lucas-Lehmer素性測試來檢查2^p - 1是否為梅森素數。** @param p 用于計算2^p - 1的指數* @return 如果2^p - 1是素數,則返回true,否則返回false*/public static boolean lucasLehmerPrime(int p) {if (p == 2) {return true; // 2^2 - 1是最小的梅森素數}BigInteger s = BigInteger.valueOf(4); // 初始值BigInteger M = BigInteger.ONE.shiftLeft(p).subtract(BigInteger.ONE); // 計算2^p - 1for (int i = 0; i < p - 2; i++) {// 應用Lucas-Lehmer迭代過程s = s.multiply(s).subtract(BigInteger.valueOf(2)).mod(M);}return s.equals(BigInteger.ZERO); // 如果s為0,則2^p - 1是素數}/*** 尋找并打印所有小于給定限制的完美數** @param limit 完美數搜索的上限值*/public static void findPerfectNumbers(BigInteger limit) {int p = 2; // 從最小的梅森素數候選指數開始int count = 0;while (true) {if (lucasLehmerPrime(p)) {// 如果找到梅森素數,計算相應的完美數BigInteger mersennePrime = BigInteger.ONE.shiftLeft(p).subtract(BigInteger.ONE);BigInteger perfectNumber = BigInteger.ONE.shiftLeft(p - 1).multiply(mersennePrime);// 統計找到的完美數數量count++;// 打印梅森素數和對應的完美數System.out.println("梅森素數: " + mersennePrime);System.out.println("完 美 數: " + perfectNumber);// 如果完美數大于給定限制,則停止搜索if (perfectNumber.compareTo(limit) > 0) {break;}}p++; // 移動到下一個候選指數}System.out.println("找到" + count + "個完美數~");}
}
(三)運行程序
- 查看結果,在指定范圍內找到12個完美數
三、實戰小結
- 通過編寫和運行完美數尋找器程序,我們深入理解了完美數與梅森素數的內在聯系,體驗了大數計算的挑戰,并認識到了算法優化的重要性。此過程不僅鍛煉了編程技能,還激發了我們對數論奧秘的探索興趣。盡管尋找大完美數極具難度,但使用
BigInteger
類和Lucas-Lehmer測試,我們能夠有效地識別梅森素數,進而發現新的完美數。