1. 程式人生 > >藍橋杯-黃金分割數

藍橋杯-黃金分割數

  • 題目

黃金分割數0.61823… 是個無理數,這個常數十分重要,在許多工程問題中會出現。有時需要把這個數字求得很精確。

對於某些精密工程,這些的常數的精度很重要。也許你聽說過哈勃太空望遠鏡,它首次升空後就發現了一處人工加工錯誤,對那樣一個龐然大物,其實只是鏡面磨製時有比頭髮絲還細許多倍的一處錯誤而已,卻使它成了“近視眼”!!

我們如何求得黃金分割數的儘可能精確的值呢?有許多方法。

比較簡單的一種是用連分數:

                  1
黃金數 = ---------------------
                    1
         1 + -----------------
                      1
             1 + -------------
                        1
                 1 + ---------
                         1 + ...

這個連分數計算的“層數”越多,它的值越接近黃金分割數。

請你利用這一特性,求出黃金分割數的足夠精確值,要求四捨五入到小數後100位。

小數後3位的值為:0.618
小數後4位的值為:0.6180
小數後5位的值為:0.61803
小數後7位的值為:0.6180340
(注意尾部的0)

你的任務是寫出小數後100位精度的黃金分割值。

  • 程式碼

分析知道,相鄰兩個斐波那契數的比值是隨序號的增加而逐漸趨於黃金分割比的,所以可以用這個方法。但是要從第幾個開始計算呢?測試程式碼的時候,我發現從250項開始前100位就不變化了。

import java.math.BigDecimal;
import java.math.BigInteger;
import
java.math.RoundingMode; public class GoldNumber { static BigInteger[] mem = new BigInteger[252]; public static void main(String[] args) { //110==>>標度 小數點後的位數 BigDecimal a = new BigDecimal(f(250),110); BigDecimal b = new BigDecimal(f(251),110); //接近零的舍入模式。在丟棄某部分之前始終不增加數字(即截短)。注意,此舍入模式始終不會增加計算值的大小。
BigDecimal c = a.divide(b, RoundingMode.HALF_DOWN); System.out.println(c.toPlainString().substring(0,102)); } static BigInteger f(int n) { if(n==1||n==2) mem[n] = new BigInteger(""+n); else if(mem[n]==null) mem[n] = f(n-1).add(f(n-2)); return mem[n]; } }
  • 結果
0.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374

以下引自百度

確切值為(√5-1)/2 ,即黃金分割數。
黃金分割數是無理數,前面的1024位為:
0.6180339887 4989484820 4586834365 6381177203 0917980576
2862135448 6227052604 6281890244 9707207204 1893911374
8475408807 5386891752 1266338622 2353693179 3180060766
7263544333 8908659593 9582905638 3226613199 2829026788
0675208766 8925017116 9620703222 1043216269 5486262963
1361443814 9758701220 3408058879 5445474924 6185695364
8644492410 4432077134 4947049565 8467885098 7433944221
2544877066 4780915884 6074998871 2400765217 0575179788
3416625624 9407589069 7040002812 1042762177 1117778053
1531714101 1704666599 1466979873 1761356006 7087480710
1317952368 9427521948 4353056783 0022878569 9782977834
7845878228 9110976250 0302696156 1700250464 3382437764
8610283831 2683303724 2926752631 1653392473 1671112115
8818638513 3162038400 5222165791 2866752946 5490681131
7159934323 5973494985 0904094762 1322298101 7261070596
1164562990 9816290555 2085247903 5240602017 2799747175
3427775927 7862561943 2082750513 1218156285 5122248093
9471234145 1702237358 0577278616 0086883829 5230459264
7878017889 9219902707 7690389532 1968198615 1437803149
9741106926 0886742962 2675756052 3172777520 3536139362
1076738937 6455606060 5922…

  • 百度的C++程式碼
//很厲害
#include <iostream>
using namespace std;
int main (void)
{
    int d,e=2,i=0,j,k=10,N,m;
    cout<<"請輸入黃金分割數位數:\n",cin>>N,N++;
    int *a=new int[2*N],*b=new int[N],*c=new int[2*N];
    while(++i<2*N)
        a[i]=b[i/2]=c[i]=0;
    for(cout<<"0.6",a[b[1]=m=2]=4;--N>1;)
    for(b[m]=e,d=0,j=k;--j+1&&!d;)
    {
        for(c[i=2*m]=j*j%k,e=j*j/k;--i>m-2;e=d/k)
            c[i]=(d=e+b[i-m+1]*j)%k;
        for(i=d=m-1;i<2*m&&a[i]<=c[i];i++)
            (a[i]<c[i])?d=0:1;
        if(d)
            for(e=j<<1,cout<<j,i=1+2*m++;--i>m-2;)
                if((a[i]-=c[i])<0)
                a[i]+=k,a[i-1]--;
    }
    delete []a,delete []b,delete []c,cin.ignore(),cin.ignore();
    return 0;
}