A. 如何用定積分或者求極限的方法求圓周率(π) 用計算機編程計算x的三次方在0到1上的定積分。
1.如何用定積分或者求極限的方法求圓周率(π)
一、源程序
本文分析下面這個很流行的計算PI的小程序。下面這個程序初看起來似乎摸不到頭腦,
不過不用擔心,當你讀完本文的時候就能夠基本讀懂它了。
程序一:很牛的計算Pi的程序
int a=10000,b,c=2800,d,e,f[2801],g;
main() {
for(;b-c;)
f[b++]=a/5;
for(;d=0,g=c*2;c -=14,printf("%.4d",e+d/a),e=d%a)
for(b=c; d+=f[b]*a,f[b]=d%--g,d/=g--,--b; d*=b);
}
二、數學公式
數學家們研究了數不清的方法來計算PI,這個程序所用的公式如下:
1 2 3 k
pi = 2 + --- * (2 + --- * (2 + --- * (2 + ... (2 + ---- * (2 + ... ))...)))
3 5 7 2k+1
至於這個公式為什麼能夠計算出PI,已經超出了本文的能力范圍。
下面要做的事情就是要分析清楚程序是如何實現這個公式的。
我們先來驗彎敬證一下這個公式:
程序二:Pi公式驗證程序
#include "stdio.h"
void main()
{
float pi=2;
int i;
for(i=100;i>=1;i--)
pi=pi*(float)i/(2*i+1)+2;
printf("%f\n",pi);
getchar();
}
上面這個程序的結果是3.141593。
三、程序展開
在正式分析程序之前,我們需要對程序一進行一下展開。我們可以看出程序一都是使用
for循環來完成計算的,這樣做雖然可以使得程序短小,但是卻很難讀懂。根據for循環
的運行順序,我們可以把它展開為如下while循環的程序:
程序三:for轉換為while之後的程序
int a=10000,b,c=2800,d,e,f[2801],g;
main() {
int i;
for(i=0;i f[i]=a/5;
while(c!=0)
{
d=0;
g=c*2;
b=c;
while(1)
{
d=d+f[b]*a;
g--;
f[b]=d%g;
d=d/g;
g--;
b--;
if(b==0) break;
d=d*b;
}
c=c-14;
printf("%.4d",e+d/a);
e=d%a;
}
}
註:
for([1];[2];[3]) {[4];}
的運行順序是[1],[2],[4],[3]。如果有逗號操作符,例如:d=0,g=c*2,則先運行d=0,
然後運行g=c*2,並且最終的結果是最後一個表達式的值,也就是這里的c*2。
下面我們就針對展開後的程序來分析。
四、程序分析
要想計算出無限精度的PI,我們需要上述的迭代公式運行無數次,並且其中每個分數也
是完全精確的,這在計算機中自然是無法實答迅現的。那麼基本實現思想就是迭代足夠多次
,並且每個分數也足夠精確,這樣就能夠計算出PI的前n位來。上面這個程序計算800位
,迭代公式一共迭代2800次。
int a=10000,b,c=2800,d,e,f[2801],g;
這句話中的2800就是迭代次數。
由於float或者double的精度遠遠不夠,因此程序中使用整數類型(實際是長整型),分
段運算(每次計算4位)。我們可以看到輸出語句 printf("%.4d",e+d/a); 其中%.4就是
把計算出來的4位輸出,我們看到c每次減少14( c=c-14;),而c的初始大小為2800,因
此一共就分了200段運算,並且每次輸出4位,所以一共輸出了800位。
由於使用整型數運算,因此有必要乘上一個系數,在這個程序中系數為1000,也就是說
,公式如下:
1 2 3 k
1000*pi = 2k+ --- * (2k+ --- * (2k+ --- * (2k+ ... (2k+ ---- * (2k+ ... )).
..)))
3 5 7 2k+1
這里的2k表示2000,也就是f[2801]數組初始化以後的數據,a=10000,a/5=2000,所以下面
的程序把f中的每個元素都賦值為2000:
for(i=0;i f[i]=a/5;
你可能會覺得奇怪,為什麼這里要把一個常數儲存到數組中去,請繼續往下看。
我們先來跟清鬧此蹤一下程序的運行:
while(c!=0) 假設這是第一次運行,c=2800,為迭代次數
{
d=0;
g=c*2; 這里的g是用來做k/(2k+1)中的分子
b=c; 這里的b是用來做k/(2k+1)中的分子
while(1)
{
d=d+f[b]*a; f中的所有的值都為2000,這里在計算時又把系數擴大了
a=10000倍。
這樣做的目的稍候介紹,你可以看到
輸出的時候是d/a,所以這不影
計算
g--;
f[b]=d%g; 先不管這一行
d=d/g; 第一次運行的g為2*2799+1,你可以看到g做了分母
g--;
b--;
if(b==0) break;
d=d*b; 這里的b為2799,可以看到d做了分子。
}
c=c-14;
printf("%.4d",e+d/a);
e=d%a;
}
只需要粗略的看看上面的程序,我們就大概知道它的確是使用的那個迭代公式來計算Pi
的了,不過不知道到現在為止你是否明白了f數組的用處。如果沒有明白,請繼續閱讀。
d=d/g,這一行的目的是除以2k+1,我們知道之所以程序無法精確計算的原因就是這個除
法。即使用浮點數,答案也是不夠精確的,因此直接用來計算800位的Pi是不可能的。那
么不精確的成分在哪裡?很明顯:就是那個余數d%g。程序用f數組把這個誤差儲存起來
,再下次計算的時候使用。現在你也應該知道為什麼d=d+f[b]*a;中間需要乘上a了吧。
把分子擴大之後,才好把誤差精確的算出來。
d如果不乘10000這個系數,則其值為2000,那麼運行d=d/g;則是2000/(2*2799+1),這
種整數的除法答案為0,根本無法迭代下去了。
現在我們知道程序就是把余數儲存起來,作為下次迭代的時候的參數,那麼為什麼這么
做就可以使得下次迭代出來的結果為
接下來的4位數呢?
這實際上和我們在紙上作除法很類似:
0142
/——------
7 / 1
10
7
---------------
30
28
---------------
20
14
---------------
60
.....
我們可以發現,在做除法的時候,我們通常把余數擴大之後再來計算,f中既然儲存的是
余數,而f[b]*a;則正好把這個余數擴大了a倍,然後如此循環下去,可以計算到任意精
度。
這里要說明的是,事實上每次計算出來的d並不一定只有4位數,例如第一次計算的時候
,d的值為31415926,輸出4位時候,把低四位的值儲存在e中間,e=d%a,也就是5926。
最後,這個c=c-14不太好理解。事實上沒有這條語句,程序計算出來的仍然正確。只是
因為如果迭代2800次,無論分數如何精確,最後Pi的精度只能夠達到800。
你可以把程序改為如下形式嘗試一下:
for(i=0;i<800;i++)
{
d=0;
g=c*2;
b=c;
while(1)
{
d=d+f[b]*a;
g--;
f[b]=d%g;
d=d/g;
g--;
b--;
if(b==0) break;
d=d*b;
}
// c=c-14; 不要這句話。
printf("%.4d",e+d/a);
e=d%a;
}
最後的答案仍然正確。
不過我們可以看到內循環的次數是c次,也就是說每次迭代計算c次。而每次計算後續位
數的時候,迭代次數減少14,而不影響精度。為什麼會這樣,我沒有研究。另外最後的
e+d/a,和e=d/a的作用就由讀者自己考慮吧。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
用計算機編程計算x的三次方在0到1上的定積分~~~~
這個沒找到!
數學太差~~~~
共同學習吧!~~~~
B. 什麼是極限編程
極限編程(Extreme Programming,XP)是一門針對業務和軟體開發的規則,它的作用在於將兩者的力量集中在共同的、可以達到的目標上。它是以符合客戶需要的軟體為目標而產生的一種方法論,XP使開發者能夠更有效的響應客戶的需求變化,哪怕是在軟體生命周期的後期。它強調,軟體開發是人與人合作進行的過程,因此成功的軟體開發過程應該充分利用人的優勢,而弱化人的缺點,突出了人在軟體開發過程中的作用。極端編程屬於輕量級的方法,認為文檔、架構不如直接編程來的直接。
C. 用matlab編程求斐波那趔趄數列前項比後項的極限
令F=limit f(n)/f(n+1) =limit f(n-1)/f(n)
斐波那齊數列的遞推關系
f(n+1)=f(n) +f(n-1)左右兩邊除以f(n+1)
1=f(n)/ f(n+1)+f(n-1)/f(n+1)=f(n)/裂纖察 f(n+1)+[f(n-1)/f(n)]*[f(n)/f(n+1)]
1=F+F*F
F=solve('1=F+F*F','F')
F =
- 5^(1/2)/2 - 1/2
5^(1/2)/肆茄2 - 1/2
0<f(n)/f(n+1)<1
F=limit f(n)/f(n+1)= 5^(1/豎核2)/2 - 1/2