题目描述
黄金分割数 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);
}
}
注意点解析
- 通过对题目给出的式子分析后,用下面的式子就可解出答案:
sum=1.0/sum+1.0;
sum=1/sum;
-
在这里我们不能用double来描述这两条式子,因为题目要求精确到小数点后100位,而double做不到这一点,所以我们要用到BigDecimal类。
-
for循环的时候,我先是让i循环1000次,然后输出,分析结果,再往下减少i的次数,最终取300为最终结果,不断调整i的次数是为了寻找一个稳定的数值。
-
这里在参数取100即表示小数点后100位,因为第三个参数RoundingMode.HALF_UP设置了对数值进行四舍五入了。