算法训练 || 黄金连分数(大数类)

题目描述

黄金分割数 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设置了对数值进行四舍五入了。

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