程序驗證本福特定律


一、定義

本福特定律,也稱為本福德法則,說明一堆從實際生活得出的數據中,以1為首位數字的數的出現機率約為總數的三成,接近期望值1/9的3倍。推廣來說,越大的數,以它為首幾位的數出現的機率就越低。它可用於檢查各種數據是否有造假。[1]

二、數學

本福特定律說明在b進位制中,以數n起頭的數出現的概率為

本福特定律不但適用於個位數字,連多位的數也可用。
在十進制首位數字的出現概率(%,小數點后一個位):

d p
1 30.1%
2 17.6%
3 12.5%
4 9.7%
5 7.9%
6 6.7%
7 5.8%
8 5.1%
9 4.6%

三、證明

其實對於本福特定律,到目前為止還沒有公認的證明。

大部分數據能夠滿足,也有部分數據是不滿足的,比如均勻分布的數據

1、很多數據的增長量會正比於存量(類似銀行的存款業務,存的越多,收益越多)會有這么一個公式:

ΔN/(N*Δt)=const(常數)

其中ΔN是增量,Δt是單位時間,N是存量

2、增長是指數增長,即相同時間內,翻的倍數是相同的,有

N=N0*e^(ct)

其中,當存量N0增長到N的時候,需要 t 時間,c是常數

可知,當N1增長到N2的時候,需要的時間是:

t = c'lg(N2/N1)

3、計算

t1 = c'lg(2)

t2 = c'lg(3/2)

...

tn = c'lg(n+1)/n

驗證下數據首位從 1~9 所需要的時間

t = t1 + t2 + ... + t9 = c'lg(10) = c'

P1 = t1 / t = c'lg(2)/c' = lg(2) = lg(1+1)/1 ≈ 30.1%

Pn = tn / t = lg(n+1)/n

這里聯想到老祖宗的一句話,萬事開頭難,或許是這個意思吧。其實這個定律到目前為止還沒有一個公認的證明,只是很多數據是符合本福特定律的。

四、驗證

驗證本福特定律對數字有一定的要求,必須是雜亂無章的數據,比如國家人口、GDP等

下面用斐波那契數列和隨機數驗證下

1、斐波那契數列驗證

PHP:

<?php
$size = 1000;
$arr = array(1, 2);
for($i = 2; $i < $size; $i++) {
    $arr[] = $arr[$i-1] + $arr[$i-2];
}
$sum = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
for($k = 0; $k < count($arr); $k++) {
    $index = substr($arr[$k], 0, 1);
    $sum[$index]++;
}
print_r($sum);
for($n = 1; $n < count($sum); $n++) {
    echo "首位 {$n} ,比例 " . round($sum[$n]/$size, 2) . "\n";
}
?>

輸出:

Array
(
    [0] => 0
    [1] => 300
    [2] => 177
    [3] => 125
    [4] => 96
    [5] => 80
    [6] => 67
    [7] => 57
    [8] => 53
    [9] => 45
)
首位 1 ,比例 0.3
首位 2 ,比例 0.18
首位 3 ,比例 0.13
首位 4 ,比例 0.1
首位 5 ,比例 0.08
首位 6 ,比例 0.07
首位 7 ,比例 0.06
首位 8 ,比例 0.05
首位 9 ,比例 0.05

 

2、隨機數,注意,程序的隨機數是偽隨機數,這里加上一個隨機的增長率,此外還要注意數據可能會太長導致越界,加個循環保證隨機數不超過十的十五次方

PHP:

<?php
$count = 0;
$size = 1000;
$grow = 80000;//增長率
$a = rand();
$sum = array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
for ($i = 0; $i < $size; $i++) {
    //模擬自然增長率,8w可改 
    $k = (rand() - 16384) / $grow + 1;
    $a = $a + $k * $a; 
    while (mb_strlen($a) >= 15) {
        //降下數量級對首位無影響
        $a /= 10;
    }
    $index = substr($a, 0, 1);
    $sum[$index]++;
}
print_r($sum);
for($n = 1; $n < count($sum); $n++) {
    echo "首位 {$n} ,比例 " . round($sum[$n]/$size, 2) . "\n";
}
?>

輸出:

Array
(
    [0] => 0
    [1] => 303
    [2] => 176
    [3] => 121
    [4] => 111
    [5] => 89
    [6] => 65
    [7] => 54
    [8] => 36
    [9] => 45
)
首位 1 ,比例 0.3
首位 2 ,比例 0.18
首位 3 ,比例 0.12
首位 4 ,比例 0.11
首位 5 ,比例 0.09
首位 6 ,比例 0.07
首位 7 ,比例 0.05
首位 8 ,比例 0.04
首位 9 ,比例 0.05

 

 五、結論

對於斐波那契數列和隨機數,得出來的結果是比較接近於本福特定律的,這也就是本福特定律大多數情況下可以用來驗證數據是否造假的原因

 

參考:

[1]. 本福特定律


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM