算法訓練 || 黃金連分數(大數類)

題目描述

黃金分割數 0.61803… 是個無理數,
這個常數十分重要,在許多工程問題中會出現。有時需要把這個數字求得很精確。
對於某些精密工程,常數的精度很重要。也許你聽說過哈勃太空望遠鏡,它首次升空後就發現了一處人工加工錯誤,
對那樣一個龐然大物,其實只是鏡面加工時有比頭髮絲還細許多倍的一處錯誤而已,卻使它成了 “近視眼”!!
言歸正傳,我們如何求得黃金分割數的儘可能精確的值呢?有許多方法。
比較簡單的一種是用連分數:
在這裏插入圖片描述
這個連分數計算的 “層數” 越多,它的值越接近黃金分割數。
請你利用這一特性,求出黃金分割數的足夠精確值,要求四捨五入到小數點後 100 位。
小數點後3位的值爲:0.618
小數點後4位的值爲:0.6180
小數點後5位的值爲:0.61803
小數點後7位的值爲:0.6180340
(注意尾部的0,不能忽略)
你的任務是:寫出精確到小數點後 100 位精度的黃金分割值。
注意:尾數的四捨五入! 尾數是 0 也要保留!
顯然答案是一個小數,其小數點後有 100 位數字,請通過瀏覽器直接提交該數字。
注意:不要提交解答過程,或其它輔助說明類的內容。

思路

首先看到這道題,我們很容易聯想到使用遞歸來完成,但是仔細一想,用遞歸在描述代碼的過程可能比較麻煩,除了遞歸,還可以使用像斐波那契那樣的非遞歸算法完成,在分析黃金分割數的規律之後,會發現它符合像斐波那契數列那樣,可以對其前一項和前前一項進行比值,也可以得到答案,這裏不再細說。
這裏我採用了一種更加簡單的方法,直接觀察上面式子的特點,根據四則運算就可以很快的得出答案,下面放出代碼:

import java.math.BigDecimal;
import java.math.RoundingMode;

public class 黃金連分數 {
	public static void main(String[] args) {
		BigDecimal bigdouble = new BigDecimal(1);
		BigDecimal one=new BigDecimal(1);
		for (int i = 0; i < 300; i++) {
			bigdouble=one.divide(bigdouble,100,BigDecimal.ROUND_HALF_UP);
			bigdouble=bigdouble.add(one);
		}
		bigdouble=one.divide(bigdouble,100,BigDecimal.ROUND_HALF_UP);
		System.out.println(bigdouble);
	}
}

注意點解析

  1. 通過對題目給出的式子分析後,用下面的式子就可解出答案:

sum=1.0/sum+1.0;
sum=1/sum;

  1. 在這裏我們不能用double來描述這兩條式子,因爲題目要求精確到小數點後100位,而double做不到這一點,所以我們要用到BigDecimal類。

  2. for循環的時候,我先是讓i循環1000次,然後輸出,分析結果,再往下減少i的次數,最終取300爲最終結果,不斷調整i的次數是爲了尋找一個穩定的數值。

  3. 這裏在參數取100即表示小數點後100位,因爲第三個參數RoundingMode.HALF_UP設置了對數值進行四捨五入了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章