用js写一个算法

  1. 例如,现在有40个数字,这40个数字取40到75范围内的随机数,但是这40个随机数的平均值要满足一定是
    等于我给死的一个平均数,例如63。
  2. 开始的思路是先生成39个,然后根据平均数取得第40个随机数,但是这样的话第40个数字就会不在规定的40到
    75这个范围内了。
  3. 望好心人解答
阅读 2.8k
5 个回答

你不要描述的这么麻烦,什么40个随机数的平均值是个固定值
你换一种想法,这40个随机数的和是个固定值,这不就是微信红包算法吗?简单了吧


还限制范围的话就不能用微信抢红包的方法了,这限制范围的同时还限制随机数的和,那范围内的数字概率就肯定不等了,不限定每个数的概率的话是有无数种方法的
改一改微信抢红包的方法应该是可以的,思路就是随机数一个一个生成,根据剩余的和来决定下一个随机数的生成概率分布
(微信红包先抢后抢的概率分布是不一样的,数学期望是相等的)

看你的需求。

有很简单的但是随机性差点的做法,比如你第一个随机的数是 A,那么下一个数你就直接得 abs(avg - A),只要是偶数个那么平均值就一定是给定的 avg。

谢谢各位的回答,我还是采用了先随机出前几位,然后留出最后一个数字,根据平均数去算出最后一个数字的值,如果不在这个范围内的话,就递归再次随机,直到随机出在这个范围的数字。
谢谢各位的帮忙!

40个数,均值需要是63
那这40个数的总和就要是2520
那问题就是,从40~75之间选取40个数,和是2520

const selectScope = [40, 75]
const targetAvg = 63
const selectCount = 40
const selectSum=targetAvg*selectCount

那就变成了约束随机问题:随机数之和为S的N个随机数

不要用常规思维来做这件事情, 你是用计算机, 不要怕麻烦, 既然是随机数, 就得随机得彻底.
比如: 你随机40个, 算平均值, 不是你要的, 就再随机, 直到随机的40个数的平均值是你要的为止.

参考一下这个, 还有很大的优化空间, 你可以试试改进

function randomInt(a,b){
    return Math.min(a,b) + Math.round(Math.abs(a-b) * Math.random())
}

function sum(a,b){
    return a + b;
}

function randomInts(min,max,length,average){
    var rfn = randomInt.bind(null,min,max);
    var arr = [];
    while(arr.length < length){
        arr.push(rfn());
    }
    while(arr.reduce(sum)/length != average){
        arr.shift();
        arr.push(rfn());
    }
    return arr;
}

var arr = randomInts(40,75,40,63);

-------------------------补充-------------------------

比较闲,我好事做到底, 优化后一下算法如下:

var _c1=0,_c2=0; //统计随机次数用.
//randomInt 拆成两个 方便比较两种算法.
function randomInt_(a,b){
    _c1++;
    return Math.min(a,b) + Math.round(Math.abs(a-b) * Math.random())
}
function randomInt(a,b){
    _c2++;
    return Math.min(a,b) + Math.round(Math.abs(a-b) * Math.random())
}

function sum(a,b){
    return a + b;
}

//旧算法
function randomInts1(min,max,length,average){
    var rfn = randomInt_.bind(null,min,max);
    var arr = [];
    while(arr.length < length){
        arr.push(rfn());
    }
    while(arr.reduce(sum)/length != average){
        arr.shift();
        arr.push(rfn());
    }
    return arr;
}

//改进算法
function randomInts2(min,max,length,average){
    var arr = [];
    var k = 0; //与平均数的偏移值
    // var _sum = 0;
    if(average>max || average<min) throw '参数错误!';
    function _autoRandom(){
        if(k > 0){
            return randomInt(min,average)
        }else if(k < 0){
            return randomInt(average,max);
        }else{
            return randomInt(min,max);
        }
    }
    function add(){
        var _n = _autoRandom();
        k += _n - average;
        // _sum += _n;
        arr.push(_n);
        
    }
    while(arr.length < length){
        add();
    }
    while(k != 0){
        var _s = arr.shift();
        // _sum -= _s;
        k -= _s - average;
        add();
    }
    return arr;
}

//比较两种算法
function test(a,b,c,d){
    console.log(`--取${c}个值,平均数为${d}--`);
    var arr1 = randomInts1(a,b,c,d);
    console.log('arr1 平均值:', arr1.reduce(sum)/c, ' 随机次数:',_c1);
    _c1 = 0;
    
    var arr2 = randomInts2(a,b,c,d);
    console.log('arr2 平均值:', arr2.reduce(sum)/c, ' 随机次数:',_c2);
    _c2 = 0;
}

test(40,75,40, 63);

/*
--取40个值,平均数为63--
arr1 平均值: 63  随机次数: 21147
arr2 平均值: 63  随机次数: 54
*/

稍微优化一下,差距不小.
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题