亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

js中數組實現權重概率分配的示例分析

發布時間:2021-08-02 10:42:05 來源:億速云 閱讀:165 作者:小新 欄目:web開發

小編給大家分享一下js中數組實現權重概率分配的示例分析,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

代碼如下:

/**
* js數組實現權重概率分配
* @param  Array  arr    js數組,參數類型[Object,Object,Object……]
* @return  Array        返回一個隨機元素,概率為其percent/所有percent之和,參數類型Object
* @author  shuiguang
*/
function weight_rand(arr){
  //參數arr元素必須含有percent屬性,參考如下所示
  /*
  var arr = [{
      name : '1',
      percent : 1
    }, {
      name : '2',
      percent : 2
    }, {
      name : '3',
      percent : 1
    }, {
      name : '4',
      percent : 2
    }
  ];
  */
  var total = 0;
  var i, j, percent;
  //下標標記數組,按照上面的例子,單倍情況下其組成為[1,2,2,3,4,4]
  var index = new Array();
  for (i = 0; i < arr.length; i++) {
    //判斷元素的權重,為了實現小數權重,先將所有的值放大100倍
    percent = 'undefined' != typeof(arr[i].percent) ? parseInt(arr[i].percent*100) : 0;
    for (j = 0; j < percent; j++) {
      index.push(i);
    }
    total += percent;
  }
  //隨機數值,其值介于0-5的整數
  var rand = Math.floor(Math.random() * total);
  return arr[index[rand]];
}

上面的方法雖然可行,可是遇到這樣一個問題:對于一般復雜的分配情況如1:1:1分配(相對值)可以滿足,如果遇到15%,25%,35%剩余等精確權重分配(絕對值)無法滿足。因為去計算15%:25%:35%:剩余的比例很是麻煩,于是我將上面的函數繼續修改,添加了百分比模式,比如上面的例子,分配了上面明確的百分數之后,剩余的百分比將給最后一個元素,而不用計算最后一個元素占的百分數,也不用計算各個元素的比例。代碼如下:

/**
* js數組實現權重概率分配,支持數字比模式(支持2位小數)和百分比模式(不支持小數,最后一個元素多退少補)
* @param  Array  arr  js數組,參數類型[Object,Object,Object……]
* @return  Array      返回一個隨機元素,概率為其weight/所有weight之和,參數類型Object
* @author  shuiguang
*/
function weight_rand(arr){
	//參數arr元素必須含有weight屬性,參考如下所示
	//var arr=[{name:'1',weight:1.5},{name:'2',weight:2.5},{name:'3',weight:3.5}];
	//var arr=[{name:'1',weight:'15%'},{name:'2',weight:'25%'},{name:'3',weight:'35%'}];
	//求出最大公約數以計算縮小倍數,perMode為百分比模式
	var per;
	var maxNum = 0;
	var perMode = false;
	//自定義Math求最小公約數方法
	Math.gcd = function(a,b){
		var min = Math.min(a,b);
		var max = Math.max(a,b);
		var result = 1;
		if(a === 0 || b===0){
			return max;
		}
		for(var i=min; i>=1; i--){
			if(min % i === 0 && max % i === 0){
				result = i;
				break;
			}
		}
		return result;
	};
	
	//使用clone元素對象拷貝仍然會造成浪費,但是使用權重數組對應關系更省內存
	var weight_arr = new Array();
	for (i = 0; i < arr.length; i++) {
		if('undefined' != typeof(arr[i].weight))
		{
			if(arr[i].weight.toString().indexOf('%') !== -1) {
				per = Math.floor(arr[i].weight.toString().replace('%',''));
				perMode = true;
			}else{
				per = Math.floor(arr[i].weight*100);
			}
		}else{
			per = 0;
		}
		weight_arr[i] = per;
		maxNum = Math.gcd(maxNum, per);
	}
	//數字比模式,3:5:7,其組成[0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
	//百分比模式,元素所占百分比為15%,25%,35%
	var index = new Array();
	var total = 0;
	var len = 0;
	if(perMode){
		for (i = 0; i < arr.length; i++) {
			//len表示存儲arr下標的數據塊長度,已優化至最小整數形式減小索引數組的長度
			len = weight_arr[i];
			for (j = 0; j < len; j++){
				//超過100%跳出,后面的舍棄
				if(total >= 100){
					break;
				}
				index.push(i);
				total++;
			}
		}
		//使用最后一個元素補齊100%
		while(total < 100){
			index.push(arr.length-1);
			total++;
		}
	}else{
		for (i = 0; i < arr.length; i++) {
			//len表示存儲arr下標的數據塊長度,已優化至最小整數形式減小索引數組的長度
			len = weight_arr[i]/maxNum;
			for (j = 0; j < len; j++){
				index.push(i);
			}
			total += len;
		}
	}
	//隨機數值,其值為0-11的整數,數據塊根據權重分塊
	var rand = Math.floor(Math.random()*total);
	//console.log(index);
	return arr[index[rand]];
}

var arr=[{name:'1',weight:1.5},{name:'2',weight:2.5},{name:'3',weight:3.5}];
console.log(weight_rand(arr));
var arr=[{name:'1',weight:'15%'},{name:'2',weight:'25%'},{name:'3',weight:'35%'}];
console.log(weight_rand(arr));
var prize_arr = [
	{'id':1, 'prize':'平板電腦', 'weight':1},
	{'id':2, 'prize':'數碼相機', 'weight':2},
	{'id':3, 'prize':'音箱設備', 'weight':10},
	{'id':4, 'prize':'4G優盤', 'weight':12},
	{'id':5, 'prize':'10Q幣', 'weight':22},
	{'id':6, 'prize':'下次沒準就能中哦', 'weight':50}    
];

var times = 100000;
var prize;
var pingban = 0;
var shuma = 0;
var yinxiang = 0;
var youpan = 0;
var qb = 0;
var xc = 0;
var start = new Date().getTime();

for($i=0; $i<times; $i++){
	prize = weight_rand(prize_arr);
	if(prize.prize == '平板電腦')
	{
		pingban++;
	}else if(prize.prize == '數碼相機'){
		shuma++;
	}else if(prize.prize == '音箱設備'){
		yinxiang++;
	}else if(prize.prize == '4G優盤'){
		youpan++;
	}else if(prize.prize == '10Q幣'){
		qb++;
	}else if(prize.prize == '下次沒準就能中哦'){
		xc++;
	}
}

var stop = new Date().getTime();
console.log('平板電腦:'+pingban/times+', 數碼相機:'+shuma/times+', 音箱設備:'+yinxiang/times+', 4G優盤:'+youpan/times+', 10Q幣:'+qb/times+', 下次沒準就能中哦:'+xc/times);
console.log('耗費時間:'+(stop-start)/1000+'秒');

該代碼已經通過最大公約數對下標數組進行優化,使用數字比模式已經優化到最小數值比例,百分比模式考慮性能消耗暫不支持2位小數。

寫完js版,于是很輕松改為php版本,經過10萬次循環測試,發現for循環比foreach省時間,而非網上傳的foreach比for更快。但是總體來說,js的執行速度是php的20倍左右,php的執行時間約6秒,js的執行時間約為0.346秒。

/**
* php數組實現權重概率分配,支持數字比模式(支持2位小數)和百分比模式(不支持小數,最后一個元素多退少補)
* @param  array  $arr  php數組,參數類型array(array(),array(),array()……)
* @return  array      返回一個隨機元素,概率為其percent/所有percent之和,參數類型array()
* @author  shuiguang
*/
function weight_rand($arr)
{
  //參數arr元素必須含有percent屬性,參考如下所示
  //$arr=array(array('name'=>'1','weight'=>1.5),array('name'=>'2','weight'=>1.5),array('name'=>'3','weight'=>1.5));
  //$arr=array(array('name'=>'1','weight'=>'15%'),array('name'=>'2','weight'=>'25%'),array('name'=>'3','weight'=>'35%'));
  //求出最大公約數以計算縮小倍數,perMode為百分比模式
  $perMode = false;
  $maxNum = 0;
  //自定義求最小公約數方法
  $gcd = function($a, $b)
  {
    $min = min($a, $b);
    $max = max($a, $b);
    $result = 1;
    if($a === 0 || $b === 0)
    {
      return $max;
    }
    for($i=$min; $i>=1; $i--)
    {
      if($min % $i === 0 && $max % $i === 0)
      {
        $result = $i;
        break;
      }
    }
    return $result;
  };
  //使用傳地址可能會影響后面的結果,但是使用權重數組對應關系更省內存
  $weight_arr = array();
  $arr_len = count($arr);
  for($i=0; $i<$arr_len; $i++)
  {
    if(isset($arr[$i]['weight']))
    {
      if(strpos($arr[$i]['weight'], '%') !== false)
      {
        $per = floor(str_replace('%', '', $arr[$i]['weight']));
        $perMode = true;
      }else{
        $per = floor($arr[$i]['weight']*100);
      }
    }else{
      $per = 0;
    }
    $weight_arr[$i] = $per;
    $maxNum = call_user_func($gcd, $maxNum, $per);
  }
  //數字比模式,3:5:7,其組成[0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
  //百分比模式,元素所占百分比為15%,25%,35%
  $index = array();
  $total = 0;
  if($perMode)
  {
    for($i=0; $i<$arr_len; $i++)
    {
      //$len表示存儲$arr下標的數據塊長度,已優化至最小整數形式減小索引數組的長度
      $len = $weight_arr[$i];
      for ($j = 0; $j < $len; $j++)
      {
        //超過100%跳出,后面的舍棄
        if($total >= 100)
        {
          break;
        }
        $index[] = $i;
        $total++;
      }
    }
    //使用最后一個元素補齊100%
    while($total < 100)
    {
      $index[] = $arr_len-1;
      $total++;
    }
  }else{
    for($i=0; $i<$arr_len; $i++)
    {
      //len表示存儲arr下標的數據塊長度,已優化至最小整數形式減小索引數組的長度
      $len = $weight_arr[$i]/$maxNum;
      for ($j = 0; $j < $len; $j++)
      {
        $index[] = $i;
      }
      $total += $len;
    }
  }
  //隨機數值,其值為0-11的整數,數據塊根據權重分塊
  $rand = floor(mt_rand(0, $total));
	//修復php隨機函數可以取臨界值造成的bug
  $rand = $rand == $total ? $total-1 : $rand;
  return $arr[$index[$rand]];
}

$arr=array(array('name'=>'1','weight'=>1.5),array('name'=>'2','weight'=>1.5),array('name'=>'3','weight'=>1.5));
p(weight_rand($arr));
$arr=array(array('name'=>'1','weight'=>'15%'),array('name'=>'2','weight'=>'25%'),array('name'=>'3','weight'=>'35%'));
p(weight_rand($arr));

$prize_arr = array(
	'0' => array('id'=>1, 'prize'=>'平板電腦', 'weight'=>1),
	'1' => array('id'=>2, 'prize'=>'數碼相機', 'weight'=>5),
	'2' => array('id'=>3, 'prize'=>'音箱設備', 'weight'=>10),
	'3' => array('id'=>4, 'prize'=>'4G優盤', 'weight'=>12),
	'4' => array('id'=>5, 'prize'=>'10Q幣', 'weight'=>22),
	'5' => array('id'=>6, 'prize'=>'下次沒準就能中哦', 'weight'=>50),
);

$start = time();
$result = array();
$times = 100000;
for($i=0; $i<$times; $i++)
{
	$row = weight_rand($prize_arr);
	if(array_key_exists($row['prize'], $result))
	{
		$result[$row['prize']] ++;
	}else{
		$result[$row['prize']] = 1;
	}
}
$cost = time() - $start;


p($result);
p('耗費時間:'.$cost.'秒');
function p($var)
{
  echo "<pre>";
  if($var === false)
  {
    echo 'false';
  }else if($var === ''){
    print_r("''");
  }else{
    print_r($var);
  }
  echo "</pre>";
}

php版本如果只是使用整數數字比模式,完全不用考慮數字的放大與求最小公倍數的算法,只需要做簡單的累加即可,可以大大縮短執行時間。

看完了這篇文章,相信你對“js中數組實現權重概率分配的示例分析”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

js
AI

钦州市| 柞水县| 古浪县| 鸡泽县| 张北县| 牙克石市| 慈溪市| 丹阳市| 山西省| 黄浦区| 四子王旗| 拉孜县| 饶河县| 同心县| 张家界市| 五寨县| 叙永县| 房山区| 潮州市| 收藏| 邹平县| 大方县| 静海县| 肇源县| 福清市| 平度市| 溆浦县| 株洲县| 邵东县| 厦门市| 庆云县| 石狮市| 汤原县| 晋城| 莎车县| 思南县| 北流市| 沂源县| 鄂尔多斯市| 河西区| 开封市|