数学.对于数组来说是随机的

Math.random in regards to arrays

本文关键字:随机 数组 于数组 数学      更新时间:2023-09-26

我对数组如何与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吗?

Math.round() vs. Math.floor()

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

这有点棘手,所以让我们举一个具体的例子:一个有三个元素的数组。正如vihan1086的优秀答案所解释的那样,这个数组的元素编号为0, 12。要从这个数组中随机选择一个元素,您需要获得这三个值中的任意一个的几率相等。

让我们看看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。但是 的机会是多少?

仔细看看这些范围。中间范围(.51.5) 是其他两个范围(0.51.52) 长度的两倍。我们有25%的机会获得050%的机会获得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, 12这三个值中的任何一个,因为这些范围的长度都是相同的。

保持简单

这里有一个建议:不要在一个表达式中编写所有这些代码。把它分解成简单的、不言自明的、有意义的函数。下面是我执行这个特定任务(从数组中选择一个随机元素)的方式:

// 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)即可。

它们发生了很多事情,所以我将它们分开:

<标题> math . random h1> 你的第一部分是对的。Math.random将生成一个数字>= 0和<1. Math.random可以返回0,但机会几乎是0,我认为它就像10^{-16}(你被闪电击中的可能性是它的100亿倍)。这将生成一个数字,如:

0.6687583869788796

我们先停一下

数组及其索引

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

[ 'foo', 'bar', 'baz' ]

现在索引如下:

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

使用[]:

从索引中获取条目
fooBarBazArray[0]; // foo
fooBarBazArray[2]; // baz
<标题>数组长度

现在数组的长度将不等于最大索引。如果我们数一下,它就是长度。所以上面的数组将返回3。每个数组都有一个length属性,它包含了数组的长度:

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

更多随机数学

现在让我们来看看这个随机化的东西:

Math.round(Math.random() * (mathematics.length-1))

他们有很多事情要做。让我们来分析一下:

math . random ()

首先我们生成一个随机数

*数学。长度- 1

这个随机函数的目标是生成一个随机数组索引。我们需要将长度减去1以获得最高索引。

第一部分结论

现在给我们一个范围从0到最大数组索引的数字。在前面展示的示例数组中:

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

现在他们有一个小问题:

此代码生成一个介于0和长度之间的随机数。这意味着-1不应该在那里。让我们修复这段代码:

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

运行这段代码,得到:

2.1972009977325797
1.0244733088184148
0.1671080442611128
2.0442249791231006
1.8239217158406973
<标题>

为了得到随机索引,我们必须把它从一个难看的小数变成一个漂亮的整数:Math.floor基本上会截断小数点。

数学。地板结果:

2
0
2
1
2

我们可以将这段代码放入[]中,以在随机索引处选择数组中的项。

更多信息/来源

  • 随机数
  • <
  • 更多解决方案/gh>

您正在查看简单的乘法和代码中的错误。它应该引用你正在选择的数组"示例",而不是你没有提到的所谓的"数学":

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

那么你只是将一个随机数乘以数组中的元素数。所以最大的随机数是1,如果你的数组中有50个元素,你把随机数乘以50,现在最大的随机数是50。

所有较小的随机数(0到1)也缩放了50倍,现在从(0到50)分布,对它们具有大致相同的随机性。然后将其四舍五入到最接近的整数,这是数组从1到n的随机索引,您可以执行element[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 × 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。

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

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