假設有兩種微生物X和Y,X出生后每隔3分鍾分裂一次(數目加倍),Y出生后每隔2分鍾分裂一次(數目加倍)。
一個新出生的X,半分鍾之后吃掉1個Y,並且,從此開始,每隔1分鍾吃1個Y。
現在已知有新出生的X=10, Y=89,求60分鍾后Y的數目。
如果X=10,Y=90呢?
編程解決這個問題比較簡單,只要以步長30秒不斷進行迭代,直到時間到達60分鍾即可。下面是用Java編寫的程序。
整個程序分為4個類:
TestBacterium是測試主類。
Xs和Ys表示X和Y的集合,它們都包含divide()方法,執行分裂操作。
Xs有方法needToEat( ),返回在某個時間點,Xs需要吃多少個Ys;相應地,Ys有表示被吃的方法beenEaten( )。如果在某次被吃之后Ys的數量降至0,則beenEaten( )方法會拋出NoMoreYException異常。
Xs類
public class Xs { private int num ; public Xs(int num) { this.num = num; } public int needToEat(int time) { if (time <= 0) return 0; if (time % 60 == 30) return num; return 0; } public void divide(int time) { if (time <= 0) return; if (time % 180 == 0) { num *= 2; } } public int amount() { return num ; } }
這里要說明一下needToEat()方法。題目中說明:X出生后半分鍾吃掉1個Y,之后每隔1分鍾吃掉1個Y,並且每3分鍾分裂一次。也就是說,X會在30、90、150秒的時間點上吃Y;接下來,在180秒時,會分裂一次,假設原來的為x1,新分裂出來的為x2,那么在下一個30秒,即在210秒時,x1和x2都要吃掉1個Y。發現規律了嗎?實際上無論經過多久,每個X都會在(n分+30秒)的時間點上吃掉1個Y,並在180秒的整數倍時間點上分裂一次。
Ys類
public class Ys { private int num ; public Ys(int num) { this.num = num; } public void beenEaten(int eatenNum) throws NoMoreYException { if (num <= eatenNum) { num = 0; throw new NoMoreYException(); } num -= eatenNum; } public void divide(int time) { if (time <= 0) return; if (time % 120 == 0) { num *= 2; } } public int amount() { return num ; } }
TestBacterium類
public class TestBacterium { private Xs x; private Ys y; public TestBacterium(int numX, int numY) { x = new Xs(numX); y = new Ys(numY); } public void startTick(int timeLong) { int time = 0; System.out.println("At the beginning, we have:"); while (time <= timeLong) { System.out.print(time + ": "); x.divide(time); y.divide(time); try { y.beenEaten(x.needToEat(time)); } catch (NoMoreYException e) { System.out.println("No more Ys, they have been eaten up. " + "Meanwhile, there are " + x.amount() + " Xs."); return; } time += 30; System.out.println(x.amount() + ", " + y.amount()); } } /** * Test bacterium. */ public static void main(String[] args) { TestBacterium t1 = new TestBacterium(10, 89); t1.startTick(3600); TestBacterium t2 = new TestBacterium(10, 90); t2.startTick(3600); } }
NoMoreYException類
package bacterium2; public class NoMoreYException extends Exception { }
運行程序,輸出如下。
Y初始數量為89: At the beginning, we have: 0: 10, 89 30: 10, 79 60: 10, 79 …… 2310: 40960, 8192 2340: 81920, 8192 2370: No more Ys, they have been eaten up. Meanwhile, there are 81920 Xs. Y初始數量為90: At the beginning, we have: 0: 10, 90 30: 10, 80 60: 10, 80 90: 10, 70 …… 3540: 5242880, 52428800 3570: 5242880, 47185920 3600: 10485760, 94371840
到此還沒有結束……
這個問題本身比較簡單,但它表現出的一個現象卻非常不簡單:初始條件的一點細微差別,可能導致結果的巨大差別。
Y的初始數量分別為89和90,相差非常小(小於1.2%),但結果卻是前者Y在2370秒時被吃完,而后者Y最終達到了接近1億的數量。
如果一個系統的演變過程對初態非常敏感,就稱它為混沌系統。一門新學科,即混沌學(Chaos),專門研究這種混沌運動。
最初發現這一現象的是美國麻省理工學院的氣象學家洛倫茲(Lorenz)。為了預報天氣,他用計算機求解仿真地球大氣的13個方程式,意圖是利用計算機的高速運算來提高長期天氣預報的准確性。1963年的一次試驗中,為了更細致地考察結果,他把一個中間解0.506取出,提高精度到0.506127再送回。而當他到咖啡館喝了杯咖啡以后回來再看時卻大吃一驚:本來很小的差異,結果卻偏離了十萬八千里!再次驗算發現計算機並沒有毛病。洛倫茲發現,由於誤差會以指數形式增長,在這種情況下,一個微小的誤差隨着不斷推移造成了巨大的后果。他於是認定這為“對初始值的極端不穩定性”。
隨后他在一篇提交紐約科學院的論文中分析了這個效應:“如果這個理論被證明正確,一只海鷗扇動翅膀足以永遠改變天氣變化。”在以后的演講和論文中他用了更加有詩意的蝴蝶,因此這種現象又被稱為“蝴蝶效應”。對於蝴蝶效應最常見的闡述是:“一只蝴蝶在巴西輕拍翅膀,可以導致一個月后德克薩斯州的一場龍卷風。”
這個發現非同小可,以致當時的科學家都不理解,幾家科學雜志也都拒登他的文章,認為“違背常理”——相近的初值代入確定的方程,結果也應相近才對,怎么會偏離如此之大呢!
混沌的本質是系統的長期行為對初始條件的敏感性,是由系統內部的非線性因素引起的。線性,指量與量之間按比例、成直線的關系,在空間和時間上代表規則和光滑的運動;而非線性則指不按比例、不成直線的關系,代表不規則的運動和突變。例如兩只眼睛的視敏度是一只眼睛的幾倍?按線性來推測結論是2倍,但事實是6-10倍,這就是非線性。1+1並不等於2。
混沌不是偶然的、個別的事件,而是普遍存在於宇宙間各種各樣的宏觀及微觀系統的。混沌也不是獨立存在的科學,它與其它各門科學互相促進、互相依靠,由此派生出許多交叉學科,如混沌氣象學、混沌經濟學、混沌數學等。
有觀點認為,混沌應屬於二十世紀三大科學之一。相對論排除了絕對時空觀的牛頓幻覺,量子論排除了可控測量過程中的牛頓迷夢,混沌則排除了拉普拉斯可預見性的狂想。混沌理論將開創科學思想上又一次新的革命。混沌學說將用一個不那么可預言的宇宙來取代牛頓、愛因斯坦的有序宇宙,混沌學者認為傳統的時鍾宇宙與真實世界毫不相關。