# 得到一个集中在中心的随机数

2020/10/11 12:41 · javascript ·  · 0评论

``````function weightedRandom(max, numDice) {
let num = 0;
for (let i = 0; i < numDice; i++) {
num += Math.random() * (max/numDice);
}
return num;
}
``````

JSFiddle：http : //jsfiddle.net/797qhcza/1/

• 我有一个大约在0和1之间均匀分布的随机数的来源
• 我希望产生一个遵循不同分布的随机数序列。

http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/

``````\$(function () {
\$('button').click(function () {
var outOfBoundsChance = .2;
var num = 0;
if (Math.random() <= outOfBoundsChance) {
num = getRandomInt(1, 100);
} else {
num = getRandomInt(40, 60);
}
\$('#out').text(num);
});

function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
});``````
``````<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<button>Generate</button>
<div id="out"></div>``````

``````var choice = Math.random() * 3;
var result;

if (choice < 2){
result = Math.random() * 20 + 40; //you have 2/3 chance to go there
}
else {
result = Math.random() * 100 + 1;
}
``````

``````var loops = 10;
var tries = 10;
var div = \$("#results").html(random());
function random() {
var values = "";
for(var i=0; i < loops; i++) {
var numTries = tries;
do {
var num = Math.floor((Math.random() * 100) + 1);
numTries--;
}
while((num < 40 || num >60) && numTries > 1)
values += num + "<br/>";
}
return values;
}``````
``````<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="results"></div>``````

`.05 / .1 = 0.5`，当映射到时`[61, 100]`我们就有收益`81`

``````/*
* Function that returns a function that maps random number to value according to map of probability
*/
function createDistributionFunction(data) {
// cache data + some pre-calculations
var cache = [];
var i;
for (i = 0; i < data.length; i++) {
cache[i] = {};
cache[i].valueMin = data[i].values[0];
cache[i].valueMax = data[i].values[1];
cache[i].rangeMin = i === 0 ? 0 : cache[i - 1].rangeMax;
cache[i].rangeMax = cache[i].rangeMin + data[i].weight;
}
return function(random) {
var value;
for (i = 0; i < cache.length; i++) {
// this maps random number to the bracket and the value inside that bracket
if (cache[i].rangeMin <= random && random < cache[i].rangeMax) {
value = (random - cache[i].rangeMin) / (cache[i].rangeMax - cache[i].rangeMin);
value *= cache[i].valueMax - cache[i].valueMin + 1;
value += cache[i].valueMin;
return Math.floor(value);
}
}
};
}

/*
* Example usage
*/
var distributionFunction = createDistributionFunction([
{ weight: 0.1, values: [1, 40] },
{ weight: 0.8, values: [41, 60] },
{ weight: 0.1, values: [61, 100] }
]);

/*
* Test the example and draw results using Google charts API
*/
function testAndDrawResult() {
var counts = [];
var i;
var value;
// run the function in a loop and count the number of occurrences of each value
for (i = 0; i < 10000; i++) {
value = distributionFunction(Math.random());
counts[value] = (counts[value] || 0) + 1;
}
// convert results to datatable and display
for (value = 0; value < counts.length; value++) {
if (counts[value] !== undefined) {
}
}
chart.draw(data);
}
``````<script src="https://www.google.com/jsapi"></script>
<div id="chart"></div>``````

``````function weighted() {

var w = 4;

// number 1 to w
var r = Math.floor(Math.random() * w) + 1;

if (r === 1) { // 1/w goes to outside 40-60
var n = Math.floor(Math.random() * 80) + 1;
if (n >= 40 && n <= 60) n += 40;
return n
}
// w-1/w goes to 40-60 range.
return Math.floor(Math.random() * 21) + 40;
}

function test() {
var counts = [];

for (var i = 0; i < 2000; i++) {
var n = weighted();
if (!counts[n]) counts[n] = 0;
counts[n] ++;
}
var output = document.getElementById('output');
var o = "";
for (var i = 1; i <= 100; i++) {
o += i + " - " + (counts[i] | 0) + "\n";
}
output.innerHTML = o;
}

test();``````
``<pre id="output"></pre>``

``````var loops = 10; //Number of numbers generated
var min = 1,
max = 50;
var div = \$("#results").html(random());

function random() {
var values = "";
for (var i = 0; i < loops; i++) {
var one = generate();
var two = generate();
var ans = one + two - 1;
var num = values += ans + "<br/>";
}
return values;
}

function generate() {
return Math.floor((Math.random() * (max - min + 1)) + min);
}``````
``````<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="results"></div>``````

``````rbeta = function(alpha, beta) {
var a = 0
for(var i = 0; i < alpha; i++)
a -= Math.log(Math.random())

var b = 0
for(var i = 0; i < beta; i++)
b -= Math.log(Math.random())

return Math.ceil(100 * a / (a+b))
}
``````
``````var randNum;
// generate random number from 1-5
var freq = Math.floor(Math.random() * (6 - 1) + 1);
// focus on 40-60 if the number is odd (1,3, or 5)
// this should happen %60 of the time
if (freq % 2){
randNum = Math.floor(Math.random() * (60 - 40) + 40);
}
else {
randNum = Math.floor(Math.random() * (100 - 1) + 1);
}
``````

1. 结果集很小。（不超过16K数字）
2. 结果集谨慎。（仅类似于整数）

`````` 5% for [ 0,39]
90% for [40,59]
5% for [60,99]
``````

``````var f = Math.random();
if (f < 0.05) return random(0,39);
else if (f < 0.95) return random(40,59);
else return random(60,99);
``````

``````random_choose([series(0,39),series(40,59),series(60,99)],[0.05,0.90,0.05]);

function random_choose (collections,probabilities)
{
var acc = 0.00;
var r1 = Math.random();
var r2 = Math.random();

for (var i = 0; i < probabilities.length; i++)
{
acc += probabilities[i];
if (r1 < acc)
return collections[i][Math.floor(r2*collections[i].length)];
}

return (-1);
}

function series(min,max)
{
var i = min; var s = [];
while (s[s.length-1] < max) s[s.length]=i++;
return s;
}
``````

``````// 90% of random numbers should be between 40 to 60.
var weight_percentage = 90;

var focuse_on_center = ( (Math.random() * 100) < weight_percentage );

if(focuse_on_center)
{
// generate a random number within the 40-60 range.
alert (40 + Math.random() * 20 + 1);
}
else
{
// generate a random number within the 1-100 range.
alert (Math.random() * 100 + 1);
}``````

``````randomNumber = 50 + 5*gaussian()
``````

``````f(x) = -(x-0)(x-100) = -x * (x-100) = -x^2 + 100x
``````

``````F(x) = -x^3/3 + 50x^2
F(100) = 500,000/3 = 166,666.66666 (let's just use 166,666, because rounding up would make the target out of bounds)
``````

``````a = -1/3
b = 50
c = 0
d = -1 * (your random number)
``````

``````ranges - [1, 20], [21, 40], [41, 60], [61, 100]
weights - {1, 2, 100, 5}
``````

1. 所有权重之和（样本中为108）
2. 范围选择边界。它基本上是这个公式：`Boundary[n] = Boundary[n - 1] + weigh[n - 1]``Boundary[0] = 0`样品有`Boundary = {0, 1, 3, 103, 108}`

1. 生成`N`范围为[0，所有权重之和）的随机数
2. `for (i = 0; i < size(Boundary) && N > Boundary[i + 1]; ++i)`
3. `i`第一个范围并生成该范围内的随机数。