日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java遍历完数的一些思考

發布時間:2023/12/20 java 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java遍历完数的一些思考 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目:打印出1~10000以內所有的完數

1.分析1

  • 如果一個數恰好等于它的因子之和,則稱該數為“完全數”。引用百度百科-完全數,如6=1+2+3
  • 不包括數本身的所有的因子之和等于這個數,所以1不符合要求;
  • 遍歷所有2~10000的數,并且嵌套遍歷0到該數范圍內的所有預備因子,如果該數模預備因子等于0,則該預備因子為該數的因子,定義一個計數器,將所有因子累加,如果累加結果等于該數本身,即這個數為完數;
  • 為了便于比較運算效率,引入System.currentTimeMillis()方法記錄遍歷前后的系統當前毫秒值;

2.代碼:

public class PerfectNumberDemo {public static void main(String[] args) {long start = System.currentTimeMillis();for (int num = 2; num <= 10000 ; num ++ ) {int sum = 0;for (int divisor = 1 ; divisor < num ; divisor ++) {if (num % divisor == 0 ) {sum = divisor + sum;}}if (sum == num) {System.out.println(num);}}long end = System.currentTimeMillis();System.out.println("遍歷全部完數所使用的時間: " + (end - start) + " 毫秒");} } 復制代碼
  • 運行結果:

3.一點思考

  • 判斷10000這個數是否是完數需要遍歷預備因子9999次,判斷9999這個數是否是完全數需要遍歷預備因子9998次,以此類推,根據等差數列求和公式需要遍歷9998*(9999 + 2) / 2 = 49,994,999次,顯然效率很低,需要進一步優化;
  • 經過分析,完數的最大因子不會超過他本身的一半,所以可以把divisor < num改成divisor <= num / 2;
  • 繼續分析,如果數num的第2因子divisor2,則(num / divisor2)也一定是num的因子,則(num / divisor2)到num之間一定不會有因子出現,下一步預備因子遍歷范圍縮小到divisor2 ~ (num / divisor2);
  • 繼續,如果數num的第3個因子divisor3,則(num / divisor3)也一定是num的因子,則(nmu / divisor3)到(num / divisor2)之間一定不會有因子出現,下一步預備因子遍歷范圍縮小到divisor3 ~ (num / divisor3),以此類推即可;
  • 將所有因子累加到計數器sum中,然后比較sum - num == num 即可,但是有個例外;
  • 例如num=16,第3個因子divisor3是4,則(num / divisor3)還是4,因子4不能重復計入計數器,所以需要使用if ··· else if ···語句判斷兩種情況,分別累加因子;

4.代碼優化

public class PerfectNumberTest {public static void main(String[] args) {int count = 0;//定義一個計數器System.out.println("1~10000范圍內的所有完數如下:");long start = System.currentTimeMillis();for (int num = 2; num <= 10000 ; num ++ ) {int sum = 0;//定義一個因子求和公式for (int divisor = 1 ; divisor <= num / divisor ; divisor ++) {if (num % divisor == 0 && divisor != num / divisor) {//若num開根號結果不是他的因子sum = divisor + (num / divisor) + sum;//則num/divisor也一定是他的因子} else if (num % divisor == 0 && divisor == num / divisor) {//若num開根號的結果是他的因子sum = divisor + sum;//則只把因子(num/divisor重復因子)賦值給sum}}if ((sum - num) == num) {//如果因子之和-該數等于該數,則這個數就是完數count ++;//計數器加一System.out.println("第 " + count +" 完數是: " + num);//輸出完數}}long end = System.currentTimeMillis();System.out.println("遍歷全部完數所使用的時間: " + (end - start) + " 毫秒");} } 復制代碼

5.執行結果

6.說在后面

  • 本人電腦是13年購買,配置一般,所以結果僅說明運行效率問題;
  • 49,994,999+次遍歷只用了400多毫秒,也就一眨眼的功夫,一般的算法優化對運行效率提升有限;
  • int類型取值范圍到21億,代碼中有多個數累加求和,很可能求和結果超出int類型范圍,影響運行結果,所以建議求完數的范圍不要太大.

轉載于:https://juejin.im/post/5a34e6c4518825696f7e121c

總結

以上是生活随笔為你收集整理的Java遍历完数的一些思考的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。