DDR爱好者之家 Design By 杰米
今天写了一个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) "htmlcode">
/**
* 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 "<pre>";
if($var === false)
{
echo 'false';
}else if($var === ''){
print_r("''");
}else{
print_r($var);
}
echo "</pre>";
}
php版本如果只是使用整数数字比模式,完全不用考虑数字的放大与求最小公倍数的算法,只需要做简单的累加即可,可以大大缩短执行时间。
DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米
暂无评论...
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
2025年10月25日
2025年10月25日
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]