javascript 获取一个集中在中心的随机数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30492259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get a random number focused on center
提问by Darryl Huffman
Is it possible to get a random number between 1-100 and keep the results mainly within the 40-60 range? I mean, it will go out of that range rarely, but I want it to be mainly within that range... Is it possible with JavaScript/jQuery?
是否有可能获得 1-100 之间的随机数并将结果主要保持在 40-60 范围内?我的意思是,它很少会超出该范围,但我希望它主要在该范围内...... JavaScript/jQuery 有可能吗?
Right now I'm just using the basic Math.random() * 100 + 1
.
现在我只是使用基本的Math.random() * 100 + 1
.
回答by BlueRaja - Danny Pflughoeft
The simplest way would be to generate two random numbers from 0-50 and add them together.
最简单的方法是从 0-50 生成两个随机数并将它们加在一起。
This gives a distribution biased towards 50, in the same way rolling two dice biases towards 7.
这给出了偏向 50 的分布,与掷两个骰子偏向 7 的方式相同。
In fact, by using a larger number of "dice" (as @Falco suggests), you can make a closer approximation to a bell-curve:
事实上,通过使用更多的“骰子” (如@Falco 所建议的),您可以更接近钟形曲线:
function weightedRandom(max, numDice) {
var num = 0;
for (var i = 0; i < numDice; i++) {
num += Math.random() * (max/numDice);
}
return num;
}
JSFiddle: http://jsfiddle.net/797qhcza/1/
JSFiddle:http: //jsfiddle.net/797qhcza/1/
回答by Eric Lippert
You have some good answers here that give specific solutions; let me describe for you the general solution. The problem is:
您在这里有一些很好的答案,可以提供具体的解决方案;让我为您描述一下通用的解决方案。问题是:
- I have a source of more-or-less uniformlydistributed random numbers between 0 and 1.
- I wish to produce a sequence of random numbers that follow a different distribution.
- 我有一个在 0 和 1 之间或多或少均匀分布的随机数的来源。
- 我希望生成遵循不同分布的随机数序列。
The general solution to this problem is to work out the quantile functionof your desired distribution, and then apply the quantile function to the output of your uniform source.
这个问题的一般解决方案是制定出位数功能所需的分布,然后应用位数功能制服源的输出。
The quantile function is the inverseof the integralof your desired distribution function. The distribution function is the function where the area under a portion of the curve is equal to the probability that the randomly-chosen item will be in that portion.
分位数功能是反的的积分所需的分布函数。分布函数是曲线一部分下的面积等于随机选择的项目在该部分的概率的函数。
I give an example of how to do so here:
我在这里举了一个例子来说明如何做到这一点:
http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/
http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/
The code in there is in C#, but the principles apply to any language; it should be straightforward to adapt the solution to JavaScript.
那里的代码是用 C# 编写的,但这些原则适用于任何语言;使解决方案适应 JavaScript 应该很简单。
回答by iCaramba
Taking arrays of numbers, etc. isn't efficient. You should take a mapping which takes a random number between 0 to 100 and maps to the distribution you need. So in your case, you could take f(x)=-(1/25)x2+4x
to get a distribution with the most values in the middle of your range.
获取数字数组等效率不高。您应该采用一个映射,它采用 0 到 100 之间的随机数并映射到您需要的分布。因此,在您的情况下,您可以获取在您的范围中间具有最多值的分布。f(x)=-(1/25)x2+4x
回答by Bitwise Creative
I might do something like setup a "chance" for the number to be allowed to go "out of bounds". In this example, a 20% chance the number will be 1-100, otherwise, 40-60:
我可能会做一些事情,比如为允许数字“越界”设置一个“机会”。在此示例中,数字有 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/
回答by Lefty
I needed to solve this problem a few years ago and my solution was easier than any of the other answers.
几年前我需要解决这个问题,我的解决方案比任何其他答案都容易。
I generated 3 randoms between the bounds and averaged them. This pulls the result towards the centre but leaves it completely possible to reach the extremities.
我在边界之间生成了 3 个随机数并将它们取平均值。这会将结果拉向中心,但完全有可能到达四肢。
回答by max890
It looksstupid but you can use rand twice:
它看起来很愚蠢,但您可以使用 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;
}
回答by Luka Krajnc
Sure it is possible. Make a random 1-100. If the number is <30 then generate number in range 1-100 if not generate in range 40-60.
当然有可能。做一个随机的 1-100。如果数字 <30,则生成 1-100 范围内的数字,如果不在 40-60 范围内生成。
回答by kasperd
There is a lot of different ways to generate such random numbers. One way to do it is to compute the sum of multiple uniformly random numbers. How many random numbers you sum and what their range is will determine how the final distribution will look.
有很多不同的方法来生成这样的随机数。一种方法是计算多个均匀随机数的总和。您求和的随机数数量及其范围将决定最终分布的外观。
The more numbers you sum up, the more it will be biased towards the center. Using the sum of 1 random numberwas already proposed in your question, but as you notice is not biased towards the center of the range. Other answers have propose using the sum of 2 random numbersor the sum of 3 random numbers.
你总结的数字越多,它就越偏向中心。您的问题中已经提出了使用1 个随机数的总和,但正如您所注意到的,它并没有偏向于范围的中心。其他答案建议使用2 个随机数的总和或3 个随机数的总和。
You can get even more bias towards the center of the range by taking the sum of more random numbers. At the extreme you could take the sum of 99 random numbers which each were either 0 or 1. That would be a binomial distribution. (Binomial distributions can in some sense be seen as the discrete version of normal distributions). This can still in theory cover the full range, but it has so much bias towards the center that you should never expect to see it reach the endpoints.
通过取更多随机数的总和,您可以获得更多偏向范围中心的偏差。在极端情况下,您可以取 99 个随机数的总和,每个数为 0 或 1。这将是二项式分布。(二项式分布在某种意义上可以被视为正态分布的离散版本)。这在理论上仍然可以覆盖整个范围,但它对中心有很大的偏见,你永远不应该期望看到它到达端点。
This approach means you can tweak just how much bias you want.
这种方法意味着你可以调整你想要多少偏差。
回答by Salman A
You can write a function that maps random values between [0, 1)
to [1, 100]
according to weight. Consider this example:
你可以写一个随机值之间的映射功能[0, 1)
,以[1, 100]
按重量。考虑这个例子:
Here, the value 0.95
maps to value between [61, 100]
.
In fact we have .05 / .1 = 0.5
, which, when mapped to [61, 100]
, yields 81
.
在这里,值0.95
映射到 之间的值[61, 100]
。
事实上,我们有.05 / .1 = 0.5
,当映射到 时[61, 100]
,会产生81
。
Here is the function:
这是函数:
/*
* 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>
回答by ctwheels
What about using something like this:
使用这样的东西怎么样:
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>
The way I've coded it allows you to set a couple of variables:
loops= number of results
tries= number of times the function will try to get a number between 40-60 before it stops running through the while loop
我编写它的方式允许您设置几个变量:
循环= 结果
尝试次数 = 函数在停止通过 while 循环之前尝试获取 40-60 之间的数字的次数
Added bonus: It uses do while!!! Awesomeness at its best
额外奖励:它使用 do while !!!最好的令人敬畏