关于数组的Math.random

时间:2015-05-30 05:13:22

标签: javascript arrays variables random

我对数组如何与Math.random()等函数协同工作感到困惑。由于Math.random()函数选择的数字大于或等于0且小于1,因此为数组中的每个变量分配了哪个特定的数字?例如,在下面的代码中,必须选择哪个数字才能打印1?打印jaguar需要选择哪个数字?

var examples= [1, 2, 3, 56, "foxy", 9999, "jaguar", 5.4, "caveman"];
var example= examples[Math.round(Math.random() * (examples.length-1))];
console.log(example);

数组中的每个元素是否都指定了等于x/n的位置编号(x是相对于第一个元素的位置编号,而n是元素的数量?由于examples有9个元素,1位于1/9位置,而9999位于6/9位置?

4 个答案:

答案 0 :(得分:9)

Math.round()Math.floor()

首先要注意的是:Math.round()永远不是您处理Math.random()返回的值时使用的正确函数。它应该是Math.floor(),然后您不需要对-1进行length更正。这是因为Math.random()返回的值为>= 0< 1

这有点棘手,所以让我们举一个具体的例子:一个包含三个元素的数组。正如vihan1086's excellent answer所述,此数组的元素编号为012。要从此数组中选择一个随机元素,您希望获得这三个值中的任何一个的平等机会。

让我们看看Math.round( Math.random() * array.length - 1 )如何解决这个问题。数组长度为3,因此我们将Math.random()乘以2。现在,我们的值n>= 0< 2。我们将该数字舍入到最接近的整数:

如果n>= 0< .5,则会转到0
如果n>= .5< 1.5,则会转到1
如果n>= 1.5< 2,则会转到2

到目前为止一切顺利。我们有机会获得我们需要的三个值中的任何一个,0,1或2.但 的机会是什么?

仔细观察这些范围。中间范围(.5最多1.5是其他两个范围的两倍0最多.5和{{ 1}}最多1.5)。我们有25%的机会获得2 50%获得0的机会,而不是25%的机会获得1,而25% 2的机会。糟糕。

相反,我们需要将Math.random()结果乘以3的整个数组长度,因此n>= 0< 3,然后是结果:Math.floor( Math.random() * array.length )它的工作原理如下:

如果n>= 0< 1,则会转到0
如果n>= 1< 2,则会转到1 如果n>= 2< 3,则会转到2

现在我们显然有同等的机会点击012这三个值中的任何一个,因为每个范围都是相同的长度。

保持简单

这是一个建议:不要在一个表达式中写下所有这些代码。将其分解为简单的功能,这些功能不言自明且有意义。这是我喜欢做这个特定任务的方式(从数组中挑选一个随机元素):

// Return a random integer in the range 0 through n - 1
function randomInt( n ) {
    return Math.floor( Math.random() * n );
}

// Return a random element from an array
function randomElement( array ) {
    return array[ randomInt(array.length) ];
}

然后其余的代码很简单:

var examples = [ 1, 2, 3, 56, "foxy", 9999, "jaguar", 5.4, "caveman" ];
var example = randomElement( examples );
console.log( example );

看看这种方式有多简单?现在,每次想要从数组中获取随机元素时,您都不必进行数学计算,只需调用randomElement(array)

答案 1 :(得分:7)

他们有点发生,所以我会分手:

的Math.random

你的第一部分是正确的。 div将生成一个&gt; = 0和&lt; 1. (function (angular) { var origMethod = angular.module; angular.module = function (name, reqs, configFn) { var module = origMethod(name, reqs, configFn); module.run(function ($rootScope) { //////////////////////////// Fixing links $rootScope.$on('$viewContentLoaded', function () { ___fixLinks($('[ng-view],ng-view,.ng-view','[ngg-app="' + name + '"]')); }); }); return module; }; })(angular); 可以返回0但是机会几乎为0我认为它就像Math.random(你被闪电击中的可能性高出100亿倍)。这将产生如下数字:

Math.random

让我们停在那里第二次

数组及其索引

数组中的每个项目都有索引或位置。范围从0 - 无穷大。在JavaScript中,数组从零开始,而不是一个。这是一张图表:

10^{-16}

现在索引如下:

0.6687583869788796

要从索引中获取项目,请使用[ 'foo', 'bar', 'baz' ]

name | index
-----|------
foo  | 0
bar  | 1
baz  | 2

数组长度

现在数组长度与最大索引不同。这将是我们计算它的长度。所以上面的数组将返回[]。每个数组都有一个fooBarBazArray[0]; // foo fooBarBazArray[2]; // baz 属性,其中包含它的长度:

3

更多随机数学

现在让我们来看看这个随机化的事情:

length

他们正在经历很多事情。让我们分解一下:

的Math.random()

首先我们生成一个随机数。

* mathematics.length - 1

此随机的目标是生成随机数组索引。我们需要从长度中减去1以获得最高指数。

第一部分结论

现在给出了一个从0到最大数组索引的数字。在我之前展示的样本数组上:

['foo', 'bar', 'baz'].length; // Is 3

现在他们有点问题了:

此代码在0和长度之间产生一个随机数。这意味着Math.round(Math.random() * (mathematics.length-1)) 不应该存在。我们来修复这段代码:

Math.random() * (['foo', 'bar', 'baz'].length - 1)

运行此代码,我得到:

-1

最后

为了得到随机索引,我们必须从一个丑陋的小数到一个好的整数:Math.random() * ['foo', 'bar', 'baz'].length 基本上会截断小数。

Math.floor结果:

2.1972009977325797
1.0244733088184148
0.1671080442611128
2.0442249791231006
1.8239217158406973

我们可以将此代码放在Math.floor中,以便在随机索引处选择数组中的项目。

更多信息/来源

答案 2 :(得分:2)

您正在查看简单的乘法,以及代码中的错误。它应该引用你选择的数组“例子”,而不是你没有提到的一些叫做“数学”的东西:

var example = examples[Math.round(Math.random() * (examples.length-1))];
                                                     ^^

然后你只是将一个随机数乘以数组中的数量。所以最大随机数是1,如果你的数组中有50个东西你将随机数乘以50,现在最大随机数是50。

所有较小的随机数(0到1)也缩放50倍,现在从(0到50)扩展到它们的随机性大致相同。然后你把它四舍五入到最接近的整数,这是一个从1到n的数组的随机索引,你可以用元素[thatnumber]来选择它。

完整示例:

Math.random()返回介于0和1之间的数字(它可以返回0,但可能性非常小):

Math.random()
0.11506261994225964
Math.random()
0.5607304393516861
Math.random()
0.5050221864582
Math.random()
0.4070177578793308
Math.random()
0.6352060229006462

将这些数字乘以某些东西来扩展它们; 1 x 10 = 10因此Math.random()* 10 = 0到10之间的随机数。

Math.random() * n 返回0到 n 之间的数字:

Math.random() * 10
2.6186012867183326
Math.random() * 10
5.616868671026196
Math.random() * 10
0.7765205189156167
Math.random() * 10
6.299650241067698

然后Math.round(number)关闭小数,并将最接近的整数留在1到10之间:

Math.round(Math.random() * 10)
5

然后选择那个编号的元素:

examples[  Math.round(Math.random() * 10)  ];

你使用.length-1因为索引从0开始计数并在长度为1时结束(参见@ vihan1086的解释,它有很多关于数组索引的说明)。

这种方法不是很随机 - 特别是它不太可能选择第一个和最后一个元素。我没有意识到我写这篇文章的时候,但@Michael Geary的回答要好得多 - 避免使用Math.round()而不使用length-1。

答案 3 :(得分:0)

这是一个古老的问题,但是我将提供一个新的,更短的解决方案来从数组中获取随机项。

Math.random

它返回0到1之间的数字(包括1个)。

按位不是~

此运算符的行为是返回您提供的相反值,因此:

a = 5
~a // -5

它也忘记了小数,例如:

a = 5.95
~a // -5

它正在跳过小数点,因此它的行为类似于 Math.floor (当然,不返回负值)。

运算符加倍

用于强制转换为布尔类型的负逻辑运算符!!!null // false,我们通过双重否定来强制使用它。 如果我们对数字使用相同的想法,那么如果执行以下操作,我们将强制将数字降到最低:~~5.999 // 5

因此

TLDR;

getRandom = (arr, len = arr.length) => arr[~~(Math.random() * len)]

示例:

getRandom([1,2,3,4,5]) // random item between 1 and 5