我对数组如何与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
位置?
答案 0 :(得分:9)
Math.round()
与Math.floor()
首先要注意的是:Math.round()
永远不是您处理Math.random()
返回的值时使用的正确函数。它应该是Math.floor()
,然后您不需要对-1
进行length
更正。这是因为Math.random()
返回的值为>= 0
和< 1
。
这有点棘手,所以让我们举一个具体的例子:一个包含三个元素的数组。正如vihan1086's excellent answer所述,此数组的元素编号为0
,1
和2
。要从此数组中选择一个随机元素,您希望获得这三个值中的任何一个的平等机会。
让我们看看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
。
现在我们显然有同等的机会点击0
,1
或2
这三个值中的任何一个,因为每个范围都是相同的长度。
这是一个建议:不要在一个表达式中写下所有这些代码。将其分解为简单的功能,这些功能不言自明且有意义。这是我喜欢做这个特定任务的方式(从数组中挑选一个随机元素):
// 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)
他们有点发生,所以我会分手:
你的第一部分是正确的。 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
他们正在经历很多事情。让我们分解一下:
首先我们生成一个随机数。
此随机的目标是生成随机数组索引。我们需要从长度中减去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)
这是一个古老的问题,但是我将提供一个新的,更短的解决方案来从数组中获取随机项。
它返回0到1之间的数字(包括1个不)。
~
此运算符的行为是返回您提供的相反值,因此:
a = 5
~a // -5
它也忘记了小数,例如:
a = 5.95
~a // -5
它正在跳过小数点,因此它的行为类似于 Math.floor (当然,不返回负值)。
用于强制转换为布尔类型的负逻辑运算符!
是!!null // false
,我们通过双重否定来强制使用它。
如果我们对数字使用相同的想法,那么如果执行以下操作,我们将强制将数字降到最低:~~5.999 // 5
因此
getRandom = (arr, len = arr.length) => arr[~~(Math.random() * len)]
示例:
getRandom([1,2,3,4,5]) // random item between 1 and 5