if elseif else條件語句的計算量問題

咱們常常用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這種),邏輯與的短路問題,節約時間.

相關文章
相關標籤/搜索