咱們常常用if elseif else這種條件語句去作分支處理,以前遇到這種語句時就有點困惑,哪一種條件語句放前面,哪一種放後面,不一樣順序是否有計算量和效率上的不一樣?在計算量小的時候,其實分別是不大的,可是隨着代碼量的不斷增多,運算量愈來愈大,特別是未來大數據和機器學習等海量數據處理的時候,算法的優點就更加明顯.Ps: alphaGo Zero用的處理器只有alphaGo的十分之一,算力不強大,但算法的優點卻一舉讓它成功戰勝阿爾法狗,也印證了算法之於算力的關係,可見算法的重要性.此次用一個小例子來講明代碼的計算量優化的問題.php
假設咱們有兩個箱子,每一個箱子裏有從1到10一共10個球,同時從兩個箱中分別取一個球,若是兩個數都大於8,則中獎.如今要寫一個代碼,判斷是否中獎.算法
思路:咱們知道中獎的機率是(2/10)^2=0.04,是一個小几率事件,因此咱們分別從兩個方向來統計代碼的計算量,一個從大機率開始判斷,一個從小几率開始判斷.機器學習
從大機率開始判斷性能
//運算次數初始化 $times = 0; //先判斷大機率事件 for ($i=1;$i<=10;$i++) { for ($j=1;$j<=10;$j++) { if ($i<=8 && $j<=8) { //若是兩個數都小於等於8,則此次判斷的運算量爲3,運算量+3 $times += 3; } elseif ($i<=8 && $j>8) {/*若是第一個數小於等於8第二個數大於8,則此次判斷的計算量爲6 (由於它首先判斷了本身不符合上一個條件,此時計算量爲3,而後在這裏又作了 一個計算量爲3的第二次判斷,因此總共的計算量爲6)*/ $times += 6; } elseif ($i>8 && $j<=8) {/*到達這裏用了7次運算,這裏第一個數大於8,因此在到達第一個條件時 的第一個判斷時就爲假,而因爲php的短路與機制,後面的第二個判斷就沒有執行,因此第一個條件 執行了2次運算,同理,第二個條件也執行了2次運算,到達本條件時執行了3次運算,因此一共是7次運算*/ $times += 7; } else {//到這裏一共經歷了2+2+2=6次判斷 $times += 6; } } } echo $times; //輸出運算量,一共424次運算
從小几率開始判斷學習
$times = 0; //先判斷小几率事件 for ($i=1;$i<=10;$i++) { for ($j=1;$j<=10;$j++) { if ($i>8 && $j>8) { //若是兩個數都大於8,則此次判斷的運算量爲3,運算量+3 $times += 3; } elseif ($i>8 && $j<=8) { /*若是第一個數大於8第二個數小於等於8,則此次判斷的計算量爲6 (由於它首先判斷了本身不符合上一個條件,此時計算量爲3,而後在這裏又作了 一個計算量爲3的第二次判斷,因此總共的計算量爲6)*/ $times += 6; } elseif ($i<=8 && $j<=8) { /*到達這裏用了7次運算,這裏第一個數小於等於8,因此在到達第一個條件時 的第一個判斷時就爲假,而因爲php的短路與機制,後面的第二個判斷就沒有執行,因此第一個條件 執行了2次運算,同理,第二個條件也執行了2次運算,到達本條件時執行了3次運算,因此一共是7次運算*/ $times += 7; } else { //到這裏一共經歷了2+2+2=6次判斷 $times += 6; } } } echo $times; //652次判斷
能夠看出,從機率大的條件開始判斷時,運算的次數要少,在這個案例中少20%,也就是說節約了20%的算力,若是是線性的話,則提高了25%的性能.大數據
咱們反過來試一試,假設兩個球都小於2的時候爲中獎,分別按大小几率實驗一下.優化
小几率spa
$times = 0; //先判斷小几率事件 for($i=1;$i<=10;$i++){ for($j=1;$j<=10;$j++){ if($i<=2 && $j<=2){ $times += 3; }elseif($i<=2 && $j>2){ $times += 6; }elseif($i>2 && $j<=2){ $times += 7; }else{ $times += 6; } } } echo $times; //496次判斷
大機率code
$times = 0; //先判斷大機率事件 for($i=1;$i<=10;$i++){ for($j=1;$j<=10;$j++){ if($i>2 && $j>2){ $times += 3; }elseif($i>2 && $j<=2){ $times += 6; }elseif($i<=2 && $j<=2){ $times += 7; }else{ $times += 6; } } } echo $times; //412次判斷
能夠看到,從大機率開始判斷仍然 比 從小几率開始判斷 節省了算力,在這個案例中,節省了約19%.事件
可是,能夠看出,不管是大機率仍是小几率,以2爲分界線的運算量 比 以8爲分界線的運算量更少.
412/496 vs. 424/652,雖然中獎機率都是同樣的.這是個頗有意思的問題.
大概的緣由是,從一開始判斷的順序問題,由於數字是從1到10這樣排列的,而下面的方法從小數字開始判斷的,因此就很容易進入前面的分支,節約了一些算力.
思考:
1, 大機率;
2, 順着數字變化的方向來判斷---因此在指定獲獎規則的時候能夠參考順着數字變化順序來;
3, 邏輯或(還有 or die這種),邏輯與的短路問題,節約時間.