數學知識:班佛定律
簡介:班佛定律的原理
自然界首數的機率並不是平均分配的,像是河川的長度、戶頭的金錢,甚至是請人們隨機選出的四位數字
在 \(b\) 進位制中,以數 \(n\) 起頭的數出現的機率為
$$
\begin{align*}
P(n)&=\frac{log_b(n+1)-log_b(n)}{log_b(b)-log_b(1)}\\
&=log_b(n+1)-log_b(n)\\
&=log_b(\frac{n+1}{n})\\
&=log_b(1+\frac{1}{n}) \\
\end{align*}
$$
一組平均增長的數據開始時,增長得較慢
由最初的數字 \(a\) 增長到另一個數字 \(a + 1\) 起首的數的時間
必然比 \(a + 1\) 起首的數增長到 \(a + 2\),需要更多時間,所以出現率就更高了
從數數目來說,順序從1開始數,1,2,3,...,9,從這點終結的話,所有數起首的機會似乎相同
但 9 之後的兩位數 10 至 19,以 1 起首的數又大大拋離了其他數了
而下一堆 9 起首的數出現之前,必然會經過一堆以 2,3,4,...,8 起首的數
若果這樣數法有個終結點,以 1 起首的數的出現率一般都比 9 大
或者換個角度來看
增長的速度需為幾何成長,才有此現象
因為無論是 \(2^x\)、\(10^x\)、\(e^x\),取 log 後,皆會變為線性
而由於每段分配類似梯型,因基數極大,導致上底與下底差異小,所以會由高決定機率
若是 [1,10),分別機率為 \(log_{10}(2)-log_{10}(1)\)、\(log_{10}(3)-log_{10}(2)\)...\(log_{10}(10)-log_{10}(9)\)
而若是 [10,100),分別機率為 \(log_{10}(20)-log_{10}(10)\)、\(log_{10}(30)-log_{10}(20)\)...\(log_{10}(100)-log_{10}(90)\)
實際上也是一樣的,因為 \(log\) 相減等於相除
十位數首數分配機率
人們隨性所寫出的數,銀行帳簿的存款數據,河流的區域
面積,都市的人口數據,公司的收支數據等,都會有底下的分佈比例
\(n\) | \(1\) | \(2\) | \(3\) | \(4\) | \(5\) | \(6\) | \(7\) | \(8\) | \(9\) |
\(P(n)\) | 30.1% | 17.6% | 12.5% | 9.7% | 7.9% | 6.7% | 5.8% | 5.1% | 4.6% |
\(10^x\) 首數分配
import numpy as np
import matplotlib.pyplot as plt
def getFirst(x):
if x < 10:
return int(x)
else:
return getFirst(x//10)
f = np.vectorize(getFirst)
data = np.random.rand(10000)
data = np.floor(10**data)
x = f(data)
plt.hist(x, bins=range(1, 11), density=True)
plt.show()
台股股價首數分佈
import requests
import pandas as pd
import time
from pyquery import PyQuery
import matplotlib.pyplot as plt
# 得到首位數
def getFirst(x):
if x < 10:
return int(x)
else:
return getFirst(x//10)
# 得到股票代碼
def getSymbolList():
url = "http://isin.twse.com.tw/isin/C_public.jsp?strMode=2"
dom = PyQuery(url)
data = []
for i, row in enumerate(dom('table.h4 tr').items()):
if i < 2:
continue
item = []
for j, col in enumerate(row.find('td')):
if col.text:
if j == 0: # 分開代碼與名字
item.extend(col.text.strip().split('\u3000'))
else:
item.append(col.text.strip().replace('\u3000', ''))
if item:
data.append(item)
else: # 只取上市部分
return data
return data
# Alpha Vantage API
def alphaVantage(function, symbol, interval='1min'):
url = "https://www.alphavantage.co/query"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; rv:57.0) Gecko/20100101 Firefox/57.0",
"Connection": "keep-alive",
}
api_key = "xxxx" #your key
params = {"function": function,
"symbol": symbol,
"interval": interval,
"apikey": api_key}
c = 0
while True:
page = requests.get(url, params=params)#, headers=headers)
data = page.json()
if len(data) >= 2:
return data
c += 1
if c > 5:
break
time.sleep(1)
print(data, page.url)
return data
# 得到股票價格
def getStockPrice(symbol):
history= alphaVantage('TIME_SERIES_INTRADAY', symbol)
last = history.get('Meta Data')
if last is None:
return 0.0
last = last['3. Last Refreshed']
price = history['Time Series (1min)'][last]['4. close']
if price:
print(symbol, float(price))
return float(price)
if __name__ == '__main__':
data = getSymbolList()
df = pd.DataFrame(data)
df = df.ix[:,[0,1]].dropna()
df = df.rename(index=int, columns={0:'symbol', 1:'name'})
df.ix[:, 'symbol'] = df['symbol'] + '.TW'
df.ix[:, 'price'] = 0
# 取得價格
df = df.reset_index(drop=True)
for i, symbol in enumerate(df['symbol']):
if df.ix[i, 'price'] == 0:
df.ix[i, 'price'] = getStockPrice(symbol)
df.ix[:, 'first'] = df['price'].apply(getFirst)
plt.hist(df['first'], bins=range(1, 11), density=True)
plt.show()
參考
不要相信你的直覺
Wiki 班佛定律
52 班佛法則...不會丟擲骰子的上帝?
A Statistical Derivation of the Signi cant-Digit Law
留言
張貼留言