布豐用投針實驗估計了 π 值,那麼用什麼簡單方法可以估計自然對數的底數 e 的值?


今天不是七夕嘛...那我就設計個有關情侶的實驗好了...

===================================================

大街上去邀請n對情侶,也就是2n個人

這個實驗是指數收斂的,n不需要太大,算下來差不多大於5就行...

然後準備2n張座椅編上號,讓他們玩搶座位遊戲,規定男女座位號之和越低得分越高...

重複實驗多輪,然後頒獎...(估摸著至少30,你可以分多次頒獎)

===================================================

說了這麼多...那麼和 e 到底有啥關係呢?

記錄每次是否所有的情侶座位都沒有相鄰.

這件事情發生的概率趨近於 frac{1}{e} !

PS:不要糾結倒數...布豐投針不也是 frac{2}{pi} 嘛...畢竟這倆常數都大於1啊...

-----------------------------------------------------------------------------------------

比如我們有四隊情侶,設 E_i 表示第 i 對情侶相鄰的概率.

那麼可以算得:

egin{aligned} P = 1 - Pspace(E1 cup E2 cup E3 cup E4)\ =1-frac{ 2^1{4 choose 1} 7! - 2^2{4 choose 2} 6! + 2^3{4 choose 3} 5! - 2^4{4 choose 4} 4!}{8!}\ =frac{12}{35}=0.3481481\ frac{1}{e}=0.367879 end{aligned}

-----------------------------------------------------------------------------------------

一般的,根據容斥原理:

a_n=displaystylesum_{i=0}^n (-2)^i {n choose i}frac{(2n-i)!}{(2n)!}

Mathematica說這個化簡是 2^n (2n-1)!! cdot operatorname{Hypergeometri1cF1}(-n,-2n,-2)...於是顯然極限為1/e...我不認識這種軟體.......

Forget it...我們用夾逼法來證明一下..

設: b_n=(1-frac{1}{n})^n,c_n=sum_{i=0}^n (-1)^i frac{1}{i!}

我們知道: lim_{n	oinfty}b_n=lim_{n	oinfty}c_n=frac{1}{e}

egin{aligned} c_n-a_n=sum_{i=0}^n (-1)^i frac{1}{i!}-sum_{i=0}^n (-2)^i {n choose i}frac{(2n-i)!}{(2n)!}\ =sum_{i=0}^n (-1)^ifrac{1}{i!}igg[1-frac{2^{i}n!}{(n-i)!}frac{(2n-i)!}{(2n)!}igg]\ ecause frac{2^{i}n!}{(n-i)!}frac{(2n-i)!}{(2n)!}=frac{(2n)(2n-2)(2n-4)cdots(2n-2i+2)}{(2n)(2n-1)(2n-2)cdots(2n-i+1)}<1\ 	hereforefrac{1}{i!}igg[1-frac{2^{i}n!}{(n-i)!}frac{(2n-i)!}{(2n)!}igg]>0\ 	herefore a_n<c_n end{aligned}

同樣的:

egin{aligned} a_n-b_n=sum_{i=0}^n (-2)^i {n choose i}frac{(2n-i)!}{(2n)!}-sum_{i=0}^n {nchoose i}ig(frac{-1}{n}ig)^i\ =sum_{i=0}^n (-1)^{i} frac{1}{i!}igg[frac{2^{i}n!(2n-i)!}{(n-i)!(2n)!}-frac{n!}{(n-i)!(n^{i})}igg]\ ecause 2^{i}n^{i}=(2n)^{i}ge(2n)(2n-1)(2n-2)cdots(2n-i+1)\ 	herefore frac{1}{i!}igg[frac{2^{i}n(n-1)cdots(n-i+1)}{(2n)(2n-1)cdots(2n-i+1)}-frac{n(n-1)cdots(n-i+1)}{n^i}igg]>0\ 	herefore a_n>b_n\ end{aligned}

綜上所述,根據夾逼準則, lim_{n	oinfty}a_n=frac{1}{e}

=========================================================

祝看到答案的情侶們七夕快樂!!


今天不是七夕嘛...那我就設計個有關燒情侶的實驗好了...

===================================================

大街上去邀請n對情侶,隨便幾個排成一排

這個實驗今天應該人手是夠的,你看街邊那些排隊吃飯的,當然n越大越好啦...

然後排隊隨機報數,要求0~1之間。

之後依次相加,每次和超過一,打開爐門,燒了,記錄燒了幾人,計數器清零。

再從零開始加,又超過1了,打開爐門,燒了,記錄燒了幾人,計數器清零。

。。。

。。。

直到結束,統計平均每次燒幾人,就好了。

===================================================

說了這麼多...那麼和 e 到底有啥關係呢?

平均每次燒人e個。。。

-----------------------------------------------------------------------------------------

至於為什麼,FFF團的自己算吧...

Approximating the number $e$ through computer simulation - mathematical background

Approximate $e$ using Monte Carlo Simulation

-----------------------------------------------------------------------------------------

有情人不難,做有情人不易,祝好!


一副牌有52張,按順序標上 1,dots,52 號,然後洗牌

如果不存在正整數 m 使得從上面數第 m 張牌剛好是第 m 號,那麼稱這副牌被「完全洗亂」

多次洗牌,統計有多少次是「完全洗亂」

記總共有 p 次洗牌,其中有 q 次被「完全洗亂」,那麼就有 eapprox frac{p}{q}

牌的張數越多, frac{p}{q} 的期望越接近 e ,洗的次數越多, frac{p}{q} 越接近自己的期望

用蒙特卡洛方法模擬一下洗10000次牌得到的結果,估得 eapprox 2.70124257158

import random
l = range(52)
p = q = i = 0

while i &< 10000: random.shuffle(l) for index, c in enumerate(l): if index + 1 == c: p += 1 break else: p += 1 q += 1 i += 1 print float(p)/float(q) # 2.70124257158

其原理是因為 frac{1}{e}=lim_{n
ightarrowinfty}sum_{k=0}^nfrac{(-1)^k}{k!}e^x 的泰勒展開取 x=-1

我們用 n 表示這副牌總牌數,讓 A_m 表示所有從上數第 m 張剛好是 m 號的 (n-1)! 幅牌的集合,讓 P_m 代表「這副牌是 A_m 的子集」這個事件。

那麼至少有一張牌在自己的位置上的排列數是 igg|igcup_{m=1}^{n}A_m igg|

因為|A_1capcdotscap A_k|=cdots=|A_{n-k+1}capcdotscap A_n| ,我們得到

egin{aligned}sum_{1leq i_1<cdots< i_kleq n}|A_{i_1}capcdotscap A_{i_k}|=underbrace{ |A_1capcdotscap A_k|+cdots+|A_{n-k+1}capcdotscap A_n|}_{
m{總共space}{n choose k}
m{space 個相等的項求和 }}\={nchoose k}igg|igcap_{m=1}^{k}A_migg|end{aligned}

由容斥原理,我們得到

egin{aligned}igg|igcup_{m=1}^{n}A_m igg|= sum_{1leq ileq n}|A_i|-sum_{1le i<jle n}|A_icap A_j|+cdots +(-1)^{n+1}|A_1capcdotscap A_n|\=sum_{k=1}^n(-1)^{k+1}igg( sum_{1leq i_1 < cdots < i_kleq n}|A_{i_1}capcdotscap A_{i_k}|igg)\=sum_{k=1}^n(-1)^{k+1}{nchoose k}igg|igcap_{m=1}^{k}A_migg|\=sum_{k=1}^n(-1)^{k+1}{nchoose k}(n-k)!\=sum_{k=1}^n(-1)^{k+1}frac{n!}{k!}end{aligned}

所以這副牌被「完全洗亂」的概率 mathbb{P} left{ igcap_{m=1}^n ar{P}_m 
ight} = 1 - frac{1}{n!} igg| igcup_{m=1}^{n} A_m igg| = sum_{k=0}^n frac{(-1)^{k}}{k!} 
ightarrow frac{1}{e} quad (n 
ightarrow infty)

顯然n 越大,這個概率越接近 1/e

PS:

上面有人提到了利用泊松分布,我覺得也是一個可行的方案。

可以蹲在車站記錄每10分鐘來了多少次車,來車的數量 Xsim
m {Po}(lambda)

Recall一下泊松分布的公式mathbb{P}left{X=m
ight}=e^{-lambda}frac{lambda^m}{m!}

在車站蹲 n 個10分鐘,記 k_m 為「總共來了 m 次車的10分鐘」的數量

lambda=frac{sum mk_m}{sum k_m} ,

frac{k_m}{n}=x_m^{-lambda}frac{lambda^m}{m!}Rightarrow x_m=left(frac{nlambda^m}{k_m m!}
ight)^{frac{1}{lambda}}

任何一個 x_m 都是對 e 的估計, eapprox x_0 approx x_1approxcdots

然後可以把 x_0, x_1, dots 求個平均,得到 e 的估計

Update:

剛想到了另外一種方法,設 a>1

因為 ln a =int_1^afrac{mathrm dx}{x} ,我們可以用Monte Carlo演算法估算這個積分。

隨機變數 Xsim[1, a]Ysim[0, 1] 落在 1/x 曲線下方的概率 mathbb P(XY < 1)=frac{ln a}{a-1}

如果生成 p(X_i, Y_i) ,其中 q 組滿足 X_i Y _i < 1

那麼因為 e=a^{1/ln a} ,就有 eapprox a^{frac{p}{q(a-1)}}


一群人每人寫一張卡片,卡片上是自己的名字。把卡片收上去,打亂次序,再隨機地發給每一個人。每個人拿到的都不是自己卡片的概率趨近於 frac{1}{e} . 多做幾次這個實驗,用頻率代替概率,求倒數,就可以了。跟布豐投針實驗估算 pi 挺像的。放上推導過程。

設有 n 個人,每人拿到的都不是自己卡片的情況總共有 a_n 種可能性, a_n 滿足這樣的遞推公式,

a_n = (n-1)(a_{n-1} + a_{n-2}), n ge 3, a_{1} = 0, a_2 = 1 .

於是每個人拿到的都不是自己的卡片的概率是 p_{n} = frac{a_n}{n!}p_n 滿足這樣的遞推公式,

p_n - p_{n-1} = -frac{1}{n}(p_{n-1} - p_{n-2})

很容易得到

p_{n} - p_{n-1} = frac{(-1)^n}{n!} .

可以把 p_{n}, n ge 2 重新寫成

p_{n} = sum_{i = 2}^{n} (p_{i} - p_{i-1}) + p_1

於是就有

p_{n} = sum_{i = 2}^{n}frac{(-1)^i}{i!} = sum_{i = 0}^{n}frac{(-1)^i}{i!}

取極限,得到

lim_{n 
ightarrow infty}p_{n} = sum_{n = 0}^{infty} frac{(-1)^n}{n!} = frac{1}{e} .

證明完畢。

可以寫個程序用蒙特卡洛模擬一下。C++ 代碼如下。

#include &
#include &
#include &
#include &
#include &
using namespace std;

struct Map
{
vector& key;
vector& value;
Map(){}
Map(int n)
{
assert(n &> 0);
for (int i = 0; i &< n; ++i) { key.push_back(i); value.push_back(i); } } void setN(int n) { key.clear(); value.clear(); for (int i = 0; i &< n; ++i) { key.push_back(i); value.push_back(i); } } }; class E { private: Map map; int n; public: E(){} explicit E(int n) { map.setN(n); this-&>n = n;
}
static int random(int n)
{
assert(n &> 0);
return rand()%n;
}
void shuffle()
{
for (int i = 0; i &< n; ++i) { int index = random(n); int temp = map.value[i]; map.value[i] = map.value[index]; map.value[index] = temp; } } void shuffle(int shuffleTimes) { for (int i = 0; i &< shuffleTimes; ++i) { shuffle(); } } bool noneMatched() const { for (int i = 0; i &< n; ++i) { if (map.key[i] == map.value[i]) return false; } return true; } double sweep() { int N = 1000; int count = 0; int shuffleTimes = 40; for (int i = 0; i &< N; ++i) { shuffle(shuffleTimes); if (noneMatched()) count++; } return float(count)/float(N); } static double mean(const vector& myVector)
{
assert(myVector.size() &> 0);
double s = 0.0;
for (int i = 0; i &< myVector.size(); ++i) { s = s + myVector[i]; } return s/float(myVector.size()); } static double sigma(const vector& myVector)
{
assert(myVector.size() &> 1);
double mu = mean(myVector);
double s = 0.0;
for (int i = 0; i &< myVector.size(); ++i) { s = s + (myVector[i] - mu)*(myVector[i] - mu); } return sqrt(s/float(myVector.size()-1)); } double getFrequency() { vector& frequencies;
int sweepTimes = 100;
for (int i = 0; i &< sweepTimes; ++i) { double f = sweep(); cout &<&< i &<&< " " &<&< sweepTimes &<&< " " &<&< f &<&< endl; frequencies.push_back(f); } return mean(frequencies); } double getEulerConstant() { return 1.0/getFrequency(); } }; int main(int argc, char **argv) { int sampleNumber = 300; E machine(sampleNumber); cout &<&< machine.getEulerConstant() &<&< endl; return 0; }

測試結果:

用了300個樣本,充分打亂卡片次序,重複試驗100次,得到的結果是 e = 2.71769 ,大約可以精確到小數點後3位。

——————————————————————————————————

更新:

最近在學習Scala, 再放一個Scala版本的程序。我很意外地發現,對這個程序而言,Scala並不比C++慢.

import scala.collection.mutable.ArrayBuffer
import scala.util.Random

class MonteCarlo
{
private var key: ArrayBuffer[Int] = new ArrayBuffer[Int]()
private var value: ArrayBuffer[Int] = new ArrayBuffer[Int]()
private var sampleNumber: Int = 0
private var frequency: ArrayBuffer[Double] = new ArrayBuffer[Double]()
private var sweepTimes: Int = 0
private var shuffleTimes:Int = 0
private var binNumber = 0

def this(sampleNumber: Int) =
{
this()
this.sampleNumber = sampleNumber
for (i &<- 0 until sampleNumber) { this.key.append(i) this.value.append(i) } this.sweepTimes = 1000 this.shuffleTimes = 40 this.binNumber = 100 } def setSweepTimes(sweepTimes: Int): Unit = { this.sweepTimes = sweepTimes } def setShuffleTimes(shuffleTimes: Int): Unit = { this.shuffleTimes = shuffleTimes } def setBinNumber(binNumber: Int): Unit = { this.binNumber = binNumber } def shuffle(): Unit = { val random = new Random() for (i &<- 0 until sampleNumber) { val index: Int = random.nextInt(sampleNumber) var temp: Int = value(i) value(i) = value(index) value(index) = temp } } def shuffle(shuffleTimes: Int): Unit = { for (i &<- 0 to shuffleTimes-1) { this.shuffle() } } def noneMatched():Boolean = { for (i &<- 0 to sampleNumber - 1) { if (value(i) == key(i)) return false } return true } def sweep(): Double = { var count = 0 for (i &<- 0 to sweepTimes-1) { this.shuffle(shuffleTimes) if (noneMatched()) { count = count + 1 } } return count.toDouble/sweepTimes.toDouble } def monteCarlo(): Unit = { for (i &<- 0 to binNumber-1) { var f: Double = this.sweep() frequency.append(f) println(i + " " + binNumber + " " + f) } } def getMeanFrequency():Double = { var sum = 0.0 this.monteCarlo() for (f &<- frequency) { sum = sum + f } return sum/frequency.size.toFloat } def getEulerConstant():Double = { return 1.0/this.getMeanFrequency() } } object Euler { def main(args: Array[String]) { var sampleNumber = 30 val monteCarlo: MonteCarlo = new MonteCarlo(sampleNumber) monteCarlo.setSweepTimes(2000) monteCarlo.setBinNumber(200) println("Euler constant e = " + monteCarlo.getEulerConstant()) } }

用程序中的參數,得到的結果是 e = 2.7.........

2.7以後的數字依賴於所使用的隨機數的seed. Monte Carlo演算法很難把 e 算到很高的精度,這跟使用的程序語言無關。


我感覺直接計算來得快,畢竟階乘收斂不是蓋的


跟以前科學家驗證硬幣概率的方法類似,朝地上撒幣。

撒了N多幣之後,硬幣除了為正或反,還會有一些立在地上。

假設有n個幣立在地上,就把所有的硬幣隨機均分為n份。

數一數有多少份裡面沒有任何硬幣立著。

這個份數大約是n/e。

關鍵是n和N/n都不能太小。

如果你不想撒幣,還可以換成氪金抽卡,硬幣立起相當於抽到你想要的卡。

如果提前知道概率為p,還可以每1/p次為一組,記錄有否成功。一組全失敗的概率大約是1/e。


以下內容截取自馬丁·加德納的科普讀物《意料之外的絞刑和其他數學娛樂》


謝邀!

今天不是七夕嘛,看著那些情侶在秀恩愛你讓我們如何有心情回答問題呢?所以容我們FFF團先燒死幾對,我再告訴你,最簡單的方法就是直接計算啊,1+1+1/2+1/6+1/24+……1/n!(感謝@拉格朗 提醒,修正錯誤)

很快就能達到你要的精度。

估計圓周率的那個實驗也是,直接計算級數比買幾千根針再一遍一遍投要簡單的多,還精確的多。投針試驗也需要兩個人合作,單身狗們就不要想了。其實,想想七夕節一對對情侶一起和睦做實驗的場景,意外的很美麗。


瘋狂地存錢取錢存錢取錢


  1. 設定一個數字 x,最好滿足 x &> 20 ; 設定一個實驗次數 X,譬如 X = 1000000
  2. 初始計數 c = 0
  3. 選一對情侶,重複 x 次 { 女方隨機抽取一個在 [1,x] 之間的數字,令男方猜測該數字 },若男一次也沒有猜中, c 加 1
  4. 重複 3. 的實驗 X 次
  5. 得到 e 的估算數值 e simeq frac{X}{c}

註:設定 X 為 1000000,x 為 100,某次運行模擬,代碼給出的結果是 2.7302


用這個: X 服從某一個泊松分布 P(lambda) ,則概率:

P{X=1}=e^{-lambda} lambda 。且 mathbb{E}[X]=lambda

只是可能要去公交站台或食堂了。


這個必須強答一發了

每次說給小夥伴聽對方都似懂非懂的樣子,我自以為說的很通俗易懂啊……

我現在高一升高二的暑假,(雖然已經上課快一個月了),這個小小的發現是我在一年前,上高一軍訓後不久,一節無聊的晚自習發現的。

不知道你們有沒有想過一個問題,設銀行年利率為1,本金為1,一年後你連本帶利將收穫2元

但如果以半年算,利率為0.5,每半年利滾利算一次,一年後很顯然要多於2元,事實上是(1+1/2)∧2=2.25元

如果以月利率1/12算,結果是(1+1/12)∧12,事實上要大於2.25

以利滾利的周期作為自變數,得到函數y=(1+1/x)∧x

當時就有一種神奇的預感了……在書上看過e,只記得數值2.71828……

果然,這個函數單調遞增,我回家用計算器算了一下,總是無限逼近e

以上


商店賣東西,覺著想漲點價。

比方說要求漲價的比率合起來不能大於1,但是漲價的策略可以分很多次進行。

我可以第一次漲50%,第二次又漲50%,合起來就是1…

但怎麼能漲到價格最高??

取一個很大的n,漲n次,每次漲1/n。

這是e

一個實際點的例子是降價。

商店發出公告,表示近期要降價多次,降價比達100%。

總降價量最低的降價策略:

取一個很大的n, 每次降當前的1/n,降n次。

這是1/e

一個好玩點的例子

有這樣一種魔法,根據消耗的魔力百分比,會增加當前被施法者的所有屬性以相同的百分比。

那麼在一個施法者的輔助下,被施法者的屬性最多提升到原先的e倍。


我來說一個有意思的實驗。

七夕節到了,小明給女神小紅表白,成功抱得美人歸~

情侶嘛,一般都要干那個不可描述的事情的。

一天一次?感覺太頻繁了;兩天一次?感覺太少了。

小紅和小明就想了一個辦法:

晚上到底啪不啪,用概率決定,規則如下:

每天晚上啪啪的概率等於:1/(1+連續啪啪天數)

例如,他們已經連續啪啪5天了,這天晚上啪啪的概率就是1/6,如果運氣好,又啪啪了,我們說這是以概率1/6決定的啪啪;如果他們哪天晚上沒有啪啪,連擊天數就清零了,那麼按照公式第二天晚上必定啪啪,這是以概率1決定的啪啪。

我們來算一下他們平均多少天啪啪一次吧~

假設他們有N天晚上沒有啪啪(N很大)

那麼有N次啪啪是以概率1決定的。

那麼有N/2次啪啪是以概率1/2決定的。(N/2是期望,之後同理)

那麼有N/6次啪啪是以概率1/3決定的。

.....

.....

總的啪啪天數:N+N/2+N/6+N/24....

我們知道這個和是 N乘e

總天數是N(1+e)

所以平均1+1/e天啪啪一次

我不會告訴你我就是這個小明


N個人,每個人有一個專屬伴侶。每個人隨機盲選一個,沒人選到自己原配的概率是1/

e。


有n個不同的數,做n次有放回的抽樣實驗。沒有被抽到的概率是(1-1/n)^n。取對數後令x=1/n,即nln(1-1/n)=ln(1-1/n)/(1/n)=ln(1-x)/x,當n趨於正無窮的時候x趨於0。利用洛必塔法則可以求得結果為1/(x-1)=-1。所以最終可以知道數字沒有被抽到的概率為1/e,剩下只要統計沒被抽到的數字的比例就行了。


泰勒展開式


推薦閱讀:

如何用一個1-8隨機生成器製作一個1-7隨機數生成器?

TAG:數學 | 數學建模 | 蒙特卡洛方法 |