国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

js數組實現權重概率分配

來源:懂視網 責編:小采 時間:2020-11-27 22:30:32
文檔

js數組實現權重概率分配

js數組實現權重概率分配:今天寫了一個js控制頁面輪播的功能,如果僅僅使用隊列很簡單,但是考慮到為每一個頁面分配權重的是否變的異常復雜,使用switch和if else也無法解決,于是想到使用js數組實現,思路是將各個輪播的頁面抽象成一個對象,各個對象需要手動指定權重值,然后組成一
推薦度:
導讀js數組實現權重概率分配:今天寫了一個js控制頁面輪播的功能,如果僅僅使用隊列很簡單,但是考慮到為每一個頁面分配權重的是否變的異常復雜,使用switch和if else也無法解決,于是想到使用js數組實現,思路是將各個輪播的頁面抽象成一個對象,各個對象需要手動指定權重值,然后組成一

今天寫了一個js控制頁面輪播的功能,如果僅僅使用隊列很簡單,但是考慮到為每一個頁面分配權重的是否變的異常復雜,使用switch和if else也無法解決,于是想到使用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版本如果只是使用整數數字比模式,完全不用考慮數字的放大與求最小公倍數的算法,只需要做簡單的累加即可,可以大大縮短執行時間。

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

js數組實現權重概率分配

js數組實現權重概率分配:今天寫了一個js控制頁面輪播的功能,如果僅僅使用隊列很簡單,但是考慮到為每一個頁面分配權重的是否變的異常復雜,使用switch和if else也無法解決,于是想到使用js數組實現,思路是將各個輪播的頁面抽象成一個對象,各個對象需要手動指定權重值,然后組成一
推薦度:
標簽: 實現 js 權重
  • 熱門焦點

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 日韩欧美伊人久久大香线蕉 | 在线精品国产一区二区 | 日韩高清在线观看 | 成人日韩在线 | 一区二区国产精品 | 在线观看免费精品国自产 | 91日韩欧美 | 亚洲视频在线观 | 国产精品一区二区三区四区五区 | 99久久精品国产一区二区小说 | 韩国女主播vip| 国产在线精品一区二区 | 国产在线视频在线观看 | 一级毛片免费看 | 欧美综合在线观看 | 久久国产毛片 | 97久久精品午夜一区二区 | 欧美综合另类 | 日韩精品免费视频 | 欧美中出在线 | 91精品一区二区三区久久久久 | 久久伊人中文字幕有码 | 日韩成人在线电影 | 国产精品亚洲国产三区 | 日韩在线无 | 国产综合精品一区二区 | 欧美性第一页 | 国产美女精品久久久久中文 | 激情综合久久 | 国产日韩一区二区三区 | 熟年交尾五十路视频在线播放 | 91情侣在线偷精品国产 | 精品一区二区三区在线成人 | 久久免费精品国产72精品剧情 | 麻豆一区 | 欧美日韩中文字幕在线 | 亚洲欧美一区二区三区国产精品 | 91po国产在线精品免费观看 | 久热福利 | 欧美不卡在线视频 | 中文字幕国产欧美 |