是否可能在1-100之间获得一个随机数并将结果主要保持在40-60范围内?我的意思是,它很少会超出那个范围,但我希望它主要在那个范围内...这可用JavaScript/jQuery实现吗?
目前我只是使用基本的 Math.random() * 100 + 1
。
是否可能在1-100之间获得一个随机数并将结果主要保持在40-60范围内?我的意思是,它很少会超出那个范围,但我希望它主要在那个范围内...这可用JavaScript/jQuery实现吗?
目前我只是使用基本的 Math.random() * 100 + 1
。
最简单的方法是从0-50之间生成两个随机数,然后将它们加起来。
这会导致分布偏向于50,就像掷两个骰子偏向于7一样。
事实上,通过使用更多的“骰子”(如@Falco建议的),你可以更接近于钟形曲线的近似:
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/
这里有一些具体的解决方案,让我为您描述一下通用解决方案。问题是:
这个问题的通用解决方案是计算您所需分布的分位函数,然后将分位函数应用于均匀源的输出。
分位函数是所需分布函数的反函数。分布函数是指曲线下部分面积等于随机选择项在该部分内的概率的函数。
在此处提供如何实现它的示例:
http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/
其中的代码是 C# 的,但原理适用于任何语言;应该可以轻松地将解决方案适应到 JavaScript 中。
取数值数组等方式效率不高,应该采用一个映射函数,将0到100之间的随机数映射到所需分布。因此,在您的情况下,可以采用f(x)=-(1/25)x2+4x
来获得一个在范围中间有最多数值的分布。
x
(取自此问题):y = (Math.sin(2 * Math.PI * (x/100 - 1/4)) + 1) / 2
- Sphinxxx我可能会设置一个“机会”,让数字有可能“越界”。在这个例子中,有20%的机会数字会在1-100之间,否则在40-60之间:
$(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>
fiddle: http://jsfiddle.net/kbv39s9w/
几年前我需要解决这个问题,我的解决方案比其他答案都更为简单。
我生成了在范围内的三个随机数,并取其平均值。这将结果拉向中心,但仍然可以完全达到极端值。
BellFactor
为3时,结果与你的相同。 - Floris它看起来很蠢,但你可以使用rand两次:
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;
}
当然可以。生成1-100的随机数,如果数字小于30,则在1-100范围内生成数字,否则在40-60范围内生成。
有很多不同的方法来生成这样的随机数。其中一种方法是计算多个均匀随机数的总和。您计算的随机数数量以及它们的范围将决定最终分布的外观。
您总结的数字越多,它就越偏向于中心。在您的问题中已经提出了使用一个随机数的总和,但正如您所注意到的那样,它不偏向范围的中心。其他答案建议使用2个随机数的和或3个随机数的和。
您可以通过取更多随机数的总和来使其更加偏向范围的中心。极端情况下,您可以取99个随机数的总和,每个随机数都是0或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>
/*
* 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
var data = new google.visualization.DataTable();
data.addColumn("number", "Value");
data.addColumn("number", "Count");
for (value = 0; value < counts.length; value++) {
if (counts[value] !== undefined) {
data.addRow([value, counts[value]]);
}
}
var chart = new google.visualization.ColumnChart(document.getElementById("chart"));
chart.draw(data);
}
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(testAndDrawResult);
<script src="https://www.google.com/jsapi"></script>
<div id="chart"></div>