下午在看一個算法的時候,突然看到了一個關於圓周率的問題,如果問你圓的周長怎麼算,你肯定毫不猶豫是2πR,但是π是怎麼算出來的呢?估計我們都沒有想過,所以我們看很多算法的時候,其實只是給了我們一個公式,其實和不懂差不多不是很大。
我來調用下我薄弱的數學細胞,簡單來看一下。把一個圓如果展開,得到的就是圓的周長,即一個非精確值3.1415926。
我們來推算一下,下面的這個六邊形,如果圓心為中心,那么半徑是和六邊形的邊長度是一樣的。假設半徑長度是1,則六邊形的邊也是1。
如果要求得圓周的長度,其實就是不斷的把多邊形擴張,一條邊繼續細分為兩個角,即十二邊形,如此類推,那麼得到的結果就是一個極為精確的了。
本來想著公式應該推導起來不難,結果發現數學基礎確實不紮實。
第一次推導是按照這種標記方式來的,貌似少了個條件,在左邊各種推導,推導失敗。
然後換了個思路,重新來推導,總算有了起色。
所以我們可以很明確的知道,如果擴張後的長度和原來的長度的關係是這樣的。那麼我們就可以藉助程序來實現圓周率的算法了。
當然假設我們是不知道圓周率這個東西的,在知道了這個關聯關係後,其實可以繼續做一些推導。
比如六邊形,假設邊長為x,則6x的長度是一個最粗略的圓的周長,這樣一來,周長就是近似於6,它和半徑的關係就是6*1,按照2πR的公式來看,其實也可以理解為2R(即為直徑),當然實際周長要比6大一點。也就是我們計算π的意義了。
所以只要切分的邊足夠多,那麼得到的π的值也就更加精確。這個時候寫程序的話,可以參考如下的方式,不斷的切分。
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("請輸入割圓次數:");
int n = scan.nextInt();
cut(n);
}
static void cut(int n) {
double y = 1.0;
for (int i = 0; i <= n; i++) {
double π = 3 * Math.pow(2, i) * y;
System.out.println("第" + i + "次切割,為正" +
Math.round( 3 * Math.pow(2, i+1)) + "邊形,圓周率π≈" + π);
y = Math.sqrt(2 - Math.sqrt(4 - y * y));
}
}
}
程序的輸出如下:
請輸入割圓次數:
15
第0次切割,為正6邊形,圓周率π≈3.0
第1次切割,為正12邊形,圓周率π≈3.1058285412302498
第2次切割,為正24邊形,圓周率π≈3.132628613281237
第3次切割,為正48邊形,圓周率π≈3.139350203046872
第4次切割,為正96邊形,圓周率π≈3.14103195089053
第5次切割,為正192邊形,圓周率π≈3.1414524722853443
第6次切割,為正384邊形,圓周率π≈3.141557607911622
第7次切割,為正768邊形,圓周率π≈3.141583892148936
第8次切割,為正1536邊形,圓周率π≈3.1415904632367617
第9次切割,為正3072邊形,圓周率π≈3.1415921060430483
第10次切割,為正6144邊形,圓周率π≈3.1415925165881546
第11次切割,為正12288邊形,圓周率π≈3.1415926186407894
第12次切割,為正24576邊形,圓周率π≈3.1415926453212157
第13次切割,為正49152邊形,圓周率π≈3.1415926453212157
第14次切割,為正98304邊形,圓周率π≈3.1415926453212157
第15次切割,為正196608邊形,圓周率π≈3.1415926453212157
想像古代的人能夠計算到小數點後7位,在條件那麼簡單的情況,真是厲害。
關於圓周率計算的方法,後續再花一些時間琢磨下,比如用蒙特卡洛的算法。今天給我最大的一個收穫是讓我真正做了一些計算,能夠推導出一個看起來有些複雜的公式,看來小學初中的課程內容我開始熟悉起來了。
個人微信公眾號,歡迎掃碼關注。