如何在JavaScript中的两个指定变量之间生成随机整数,例如x=4和y=8将输出4、5、6、7、8中的任意一个?
当前回答
下面是一个JavaScript函数的示例,它可以在不使用Math.random()的情况下生成任意指定长度的随机数:
function genRandom(length)
{
const t1 = new Date().getMilliseconds();
var min = "1", max = "9";
var result;
var numLength = length;
if (numLength != 0)
{
for (var i = 1; i < numLength; i++)
{
min = min.toString() + "0";
max = max.toString() + "9";
}
}
else
{
min = 0;
max = 0;
return;
}
for (var i = min; i <= max; i++)
{
// Empty Loop
}
const t2 = new Date().getMilliseconds();
console.log(t2);
result = ((max - min)*t1)/t2;
console.log(result);
return result;
}
其他回答
使用现代JavaScript+Lodash:
const generateRandomNumbers = (max, amount) => {
const numbers = [...Array(max).keys()];
const randomNumbers = sampleSize(numbers, amount);
return randomNumbers.sort((a, b) => a - b);
};
此外,TypeScript版本:
const generateRandomNumbers = (max: number, amount: number) => {
const numbers = [...Array(max).keys()];
const randomNumbers: number[] = sampleSize(numbers, amount);
return randomNumbers.sort((a: number, b: number) => a - b);
};
Math.random()快速且适用于许多目的,但如果您需要密码安全的值(它不安全),或者如果您需要来自完全一致的无偏分布的整数(其他答案中使用的乘法方法产生某些值的频率略高于其他答案),则不适用。
在这种情况下,我们可以使用crypto.getRandomValues()生成安全整数,并拒绝任何无法统一映射到目标范围的生成值。这会比较慢,但除非您正在生成大量的值,否则这不会有意义。
为了澄清偏差分布问题,请考虑这样一种情况:我们希望生成1到5之间的值,但我们有一个随机数生成器,它生成1到16之间的值(4位值)。我们希望将相同数量的生成值映射到每个输出值,但16不能被5整除:它留下1的余数。因此,我们需要拒绝1个可能生成的值,只有当我们得到15个较小的值中的一个值时才能继续,这些值可以统一映射到我们的目标范围中。我们的行为可能类似于以下伪代码:
Generate a 4-bit integer in the range 1-16.
If we generated 1, 6, or 11 then output 1.
If we generated 2, 7, or 12 then output 2.
If we generated 3, 8, or 13 then output 3.
If we generated 4, 9, or 14 then output 4.
If we generated 5, 10, or 15 then output 5.
If we generated 16 then reject it and try again.
下面的代码使用了类似的逻辑,但生成了一个32位整数,因为这是JavaScript的标准数字类型可以表示的最大公共整数大小。(如果需要更大的范围,可以将其修改为使用BigInts。)无论选择的范围如何,生成的被拒绝值的比例始终小于0.5,因此预期的拒绝数始终小于1.0,通常接近0.0;你不必担心它会永远循环。
常量随机整数=(最小值,最大值)=>{常量范围=最大值-最小值;常量maxGeneratedValue=0xFFFFFFFF;const possibleResultValues=范围+1;const possibleGeneratedValues=最大生成值+1;常量余数=possibleGeneratedValues%possibleResultValues;const maxUnbiased=maxGeneratedValue-余数;if(!Number.isInteger(min)||!Number.isInteger(最大值)||max>Number.max_SAFE_INTEGER||min<Number.min_SAFE_INDEGER){抛出新错误(“参数必须是安全整数。”);}否则如果(范围>maxGeneratedValue){抛出新错误(`范围为${Range}(从${min}到${max})>${maxGeneratedValue}。`);}否则,如果(最大值<最小值){抛出新错误(`max(${max})必须>=min(${min})。`);}否则如果(min==max){返回最小值;} let生成;做{generated=crypto.getRandomValues(新Uint32Array(1))[0];}而(生成>maxUnbiased);return min+(生成的%possibleResultValues);};console.log(randomInteger(-8,8));//-2.console.log(randomInteger(0,0));//0console.log(随机整数(0,0xFFFFFFFF));//944450079console.log(随机整数(-1,0xFFFFFFFF));//错误:4294967296覆盖-1到4294967295的范围>4294967295。console.log(new Array(12).fill().map(n=>randomInteger(8,12)));// [11, 8, 8, 11, 10, 8, 8, 12, 12, 12, 9, 9]
这里有一个函数,它生成一个介于最小值和最大值之间的随机数,两者都包含在内。
const randomInt = (max, min) => Math.round(Math.random() * (max - min)) + min;
我的生成0和n之间的随机数的方法,其中n<=10(n除外):
Math.floor((Math.random() * 10) % n)
使用计算机程序生成随机数后,如果选取的数字是初始数字的一部分或全部,则仍将其视为随机数。但如果它被改变了,数学家就不接受它是一个随机数,他们可以称它为一个有偏数。
但是,如果您正在为一项简单的任务开发一个程序,则不需要考虑这种情况。但是,如果你正在开发一个程序,为有价值的东西(如彩票程序或赌博游戏)生成随机数,那么如果你不考虑上述情况,你的程序将被管理层拒绝。
所以对于这类人,我的建议是:
使用Math.random()生成一个随机数(说这个n):
Now for [0,10) ==> n*10 (i.e. one digit) and for[10,100) ==> n*100 (i.e., two digits) and so on. Here square bracket indicates that the boundary is inclusive and a round bracket indicates the boundary is exclusive.
然后删除小数点后的其余部分。(即,获得发言权)-使用Math.floor()。这可以完成。
如果你知道如何读取随机数表来选择一个随机数,那么你知道上面的过程(乘以1、10、100等)不会违反我在开头提到的过程(因为它只改变小数点的位置)。
研究以下示例,并根据您的需要进行开发。
如果你需要一个样本[0,9],那么n10的下限是你的答案,如果你需要[0,99],那么n100的下限就是你的答案等等。
现在让我们进入您的角色:
您已要求提供特定范围内的数字。(在这种情况下,你在这个范围内是有偏差的。通过掷骰子从[1,6]中取一个数字,那么你就有偏差到[1,6],但当且仅当骰子无偏差时,它仍然是一个随机数。)
所以考虑一下你的范围==>[78,247]范围内的元素数=247-78+1=170;(因为两个边界都包含在内)。
/* Method 1: */
var i = 78, j = 247, k = 170, a = [], b = [], c, d, e, f, l = 0;
for(; i <= j; i++){ a.push(i); }
while(l < 170){
c = Math.random()*100; c = Math.floor(c);
d = Math.random()*100; d = Math.floor(d);
b.push(a[c]); e = c + d;
if((b.length != k) && (e < k)){ b.push(a[e]); }
l = b.length;
}
console.log('Method 1:');
console.log(b);
/* Method 2: */
var a, b, c, d = [], l = 0;
while(l < 170){
a = Math.random()*100; a = Math.floor(a);
b = Math.random()*100; b = Math.floor(b);
c = a + b;
if(c <= 247 || c >= 78){ d.push(c); }else{ d.push(a); }
l = d.length;
}
console.log('Method 2:');
console.log(d);
注意:在方法一中,首先我创建了一个包含所需数字的数组,然后将它们随机放入另一个数组中。
在方法二中,随机生成数字,并检查这些数字是否在您需要的范围内。然后将其放入数组中。在这里,我生成了两个随机数,并使用它们的总数通过最小化获得有用数字的失败率来最大化程序的速度。然而,将生成的数字相加也会产生一些偏差。所以我推荐我的第一种方法来生成特定范围内的随机数。
在这两种方法中,控制台都会显示结果(在Chrome中按F12打开控制台)。
推荐文章
- 如何在单个测试基础上更改模拟实现?
- VueJS有条件地为元素添加属性
- Uncaught TypeError:(中间值)(…)不是一个函数
- 如何设置URL查询参数在Vue与Vue路由器
- 无法读取属性“addEventListener”为空
- 如何防止moment.js从webpack加载地区?
- getMonth在javascript中给出前一个月
- 如何在禁用按钮上启用引导工具提示?
- Node.js全局变量
- 在前一个函数完成后调用另一个函数
- JavaScript中两个日期之间的月份差异
- 如何同时运行两个jQuery动画?
- 如何将FormData (HTML5对象)转换为JSON
- Object.hasOwnProperty()产生ESLint 'no-prototype-builtins'错误:如何修复?
- 生成1和10之间的随机数Java