W jaki sposób można wygenerować losowe liczb całkowitych między dwoma określonymi zmiennych w JavaScript, np x = 4
i y = 8
będzie wyjście któregokolwiek 4, 5, 6, 7, 8
?
W jaki sposób można wygenerować losowe liczb całkowitych między dwoma określonymi zmiennych w JavaScript, np x = 4
i y = 8
będzie wyjście któregokolwiek 4, 5, 6, 7, 8
?
Odpowiedzi:
Istnieje kilka przykładów na stronie Mozilla Developer Network :
/**
* Returns a random number between min (inclusive) and max (exclusive)
*/
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
/**
* Returns a random integer between min (inclusive) and max (inclusive).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Oto logika. To prosta zasada trzech:
Math.random()
zwraca Number
od 0 (włącznie) do 1 (wyłącznie). Mamy więc taki interwał:
[0 .................................... 1)
Chcielibyśmy teraz liczbę pomiędzy min
(włącznie) a max
(wyłącznie):
[0 .................................... 1)
[min .................................. max)
Możemy użyć, Math.random
aby uzyskać korespondenta w przedziale [min, maks.). Ale najpierw powinniśmy wziąć pod uwagę problem, odejmując min
od drugiego przedziału:
[0 .................................... 1)
[min - min ............................ max - min)
To daje:
[0 .................................... 1)
[0 .................................... max - min)
Możemy teraz złożyć wniosek, Math.random
a następnie obliczyć korespondenta. Wybierzmy liczbę losową:
Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)
Aby znaleźć x
, zrobilibyśmy:
x = Math.random() * (max - min);
Nie zapomnij dodać z min
powrotem, aby uzyskać liczbę w przedziale [min, maks.):
x = Math.random() * (max - min) + min;
To była pierwsza funkcja z MDN. Drugi zwraca liczbę całkowitą pomiędzy min
i max
, oba włącznie.
Teraz do uzyskania liczby całkowite, można użyć round
, ceil
lub floor
.
Możesz użyć Math.round(Math.random() * (max - min)) + min
, ale daje to nierównomierną dystrybucję. Zarówno, min
a max
tylko około połowę szansę na rolce:
min...min+0.5...min+1...min+1.5 ... max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘ ← Math.round()
min min+1 max
Po max
wykluczeniu z przedziału ma jeszcze mniejszą szansę na wyrzucenie niż min
.
Dzięki temu Math.floor(Math.random() * (max - min +1)) + min
masz idealnie równomierną dystrybucję.
min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
| | | | | |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘ ← Math.floor()
min min+1 max-1 max
Nie można używać ceil()
i -1
w tym równaniu, bo max
teraz miał nieco mniejsze szanse na rolki, ale można przechylać (niechciane) min-1
skutkować zbyt.
floor
, co zaokrągla w dół.
round
, ale oba min
i max
tylko połowa szans na rzucenie , tak jak inne liczby. Możesz też odjąć jedną i wziąć ceil
. To jednak pozostawia max
liczbę z minimalną mniejszą szansą na wyrzucenie ze względu na [0,1)
Interwał.
var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;
(Math.random() * (maximum - minimum + 1) ) << 0
jest szybsze.
x << 0
, x | 0
, ~~x
) zamiast Math.floor()
nawróconych x
w dwóch uzupełnienie ze znacznie mniejszym zakresie niż Number.MAX_SAFE_INTEGER
(2³²⁻¹ vs. 2⁵³), więc trzeba go używać z rozwagą!
657348096152|0
otrzymasz 218099864 (1100111111111111000010011000 w formacie binarnym).
Zwraca całkowitą liczbę losową między min (w zestawie ) i max (w zestawie ):
function randomInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Lub dowolna liczba losowa od min (w zestawie ) do maks. ( Nie w zestawie ):
function randomNumber(min, max) {
return Math.random() * (max - min) + min;
}
Przydatne przykłady (liczby całkowite):
// 0 -> 10
Math.floor(Math.random() * 11);
// 1 -> 10
Math.floor(Math.random() * 10) + 1;
// 5 -> 20
Math.floor(Math.random() * 16) + 5;
// -10 -> (-2)
Math.floor(Math.random() * 9) - 10;
** I zawsze miło przypomnieć (Mozilla):
Math.random () nie zapewnia kryptograficznie bezpiecznych liczb losowych. Nie używaj ich do niczego związanego z bezpieczeństwem. Zamiast tego użyj interfejsu API Web Crypto, a dokładniej metody window.crypto.getRandomValues ().
function getRandomizer(bottom, top) {
return function() {
return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
}
}
stosowanie:
var rollDie = getRandomizer( 1, 6 );
var results = ""
for ( var i = 0; i<1000; i++ ) {
results += rollDie() + " "; //make a string filled with 1000 random numbers in the range 1-6.
}
awaria:
Zwracamy funkcję (zapożyczanie z programowania funkcjonalnego), która po wywołaniu zwróci losową liczbę całkowitą między wartościami bottom
i top
włącznie. Mówimy „włącznie”, ponieważ chcemy uwzględnić zarówno dolną, jak i górną część zakresu liczb, które można zwrócić. Tą drogą,getRandomizer( 1, 6 )
zwróci 1, 2, 3, 4, 5 lub 6.
(dół to niższa liczba, góra to większa liczba)
Math.random() * ( 1 + top - bottom )
Math.random()
zwraca losowy podwójny od 0 do 1, a jeśli pomnożymy go przez jeden plus różnica między top
i bottom
, otrzymamy podwójną wartość pomiędzy 0
a 1+b-a
.
Math.floor( Math.random() * ( 1 + top - bottom ) )
Math.floor
zaokrągla liczbę w dół do najbliższej liczby całkowitej. Mamy teraz wszystkie liczby całkowite między 0
i top-bottom
. 1 wygląda na mylące, ale musi tam być, ponieważ zawsze zaokrąglamy w dół, więc bez tego nigdy nie zostanie osiągnięta najwyższa liczba. Losowe dziesiętne generujemy musi mieścić się w przedziale 0
do (1+top-bottom)
tak możemy zaokrąglić w dół i uzyskać int w przedziale 0
dotop-bottom
Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom
Kod w poprzednim przykładzie dał nam liczbę całkowitą w zakresie 0
i top-bottom
tak wszyscy musimy teraz zrobić, to dodać bottom
do tego wyniku, aby uzyskać całkowitą w zakresie bottom
i top
włącznie. :RE
UWAGA: Jeśli wpiszesz najpierw wartość niecałkowitą lub większą liczbę, otrzymasz niepożądane zachowanie, ale chyba że ktoś o to poprosi, nie będę zagłębiał się w kod sprawdzania argumentów, ponieważ jest to raczej dalekie od intencji pierwotnego pytania .
function randomRange(min, max) {
return ~~(Math.random() * (max - min + 1)) + min
}
Alternatywnie, jeśli używasz Underscore.js , możesz użyć
_.random(min, max)
_.uniqueId()
funkcję, którą można wywołać dla modeli po stronie klienta.
x << 0
, x | 0
, ~~x
) zamiast Math.floor()
nawróconych x
w dwóch uzupełnienie ze znacznie mniejszym zakresie niż Number.MAX_SAFE_INTEGER
(2³²⁻¹ vs. 2⁵³), więc trzeba go używać z rozwagą!
Zwróć losową liczbę od 1 do 10:
Math.floor((Math.random()*10) + 1);
Zwróć losową liczbę od 1 do 100:
Math.floor((Math.random()*100) + 1)
Pozostałe odpowiedzi nie uwzględniają idealnie rozsądnych parametrów 0
i 1
. Zamiast tego należy używać round
zamiast z ceil
lub floor
:
function randomNumber(minimum, maximum){
return Math.round( Math.random() * (maximum - minimum) + minimum);
}
console.log(randomNumber(0,1)); # 0 1 1 0 1 0
console.log(randomNumber(5,6)); # 5 6 6 5 5 6
console.log(randomNumber(3,-1)); # 1 3 1 -1 -1 -1
console.log(randomNumber(5,6)); # 9 6 6 5 7 7
Czy 9 i 7 występują między 5 a 6? ...... powinieneś to poprawić lub wyjaśnić ...
Oto implementacja MS DotNet klasy Random w javascript-
var Random = (function () {
function Random(Seed) {
if (!Seed) {
Seed = this.milliseconds();
}
this.SeedArray = [];
for (var i = 0; i < 56; i++)
this.SeedArray.push(0);
var num = (Seed == -2147483648) ? 2147483647 : Math.abs(Seed);
var num2 = 161803398 - num;
this.SeedArray[55] = num2;
var num3 = 1;
for (var i_1 = 1; i_1 < 55; i_1++) {
var num4 = 21 * i_1 % 55;
this.SeedArray[num4] = num3;
num3 = num2 - num3;
if (num3 < 0) {
num3 += 2147483647;
}
num2 = this.SeedArray[num4];
}
for (var j = 1; j < 5; j++) {
for (var k = 1; k < 56; k++) {
this.SeedArray[k] -= this.SeedArray[1 + (k + 30) % 55];
if (this.SeedArray[k] < 0) {
this.SeedArray[k] += 2147483647;
}
}
}
this.inext = 0;
this.inextp = 21;
Seed = 1;
}
Random.prototype.milliseconds = function () {
var str = new Date().valueOf().toString();
return parseInt(str.substr(str.length - 6));
};
Random.prototype.InternalSample = function () {
var num = this.inext;
var num2 = this.inextp;
if (++num >= 56) {
num = 1;
}
if (++num2 >= 56) {
num2 = 1;
}
var num3 = this.SeedArray[num] - this.SeedArray[num2];
if (num3 == 2147483647) {
num3--;
}
if (num3 < 0) {
num3 += 2147483647;
}
this.SeedArray[num] = num3;
this.inext = num;
this.inextp = num2;
return num3;
};
Random.prototype.Sample = function () {
return this.InternalSample() * 4.6566128752457969E-10;
};
Random.prototype.GetSampleForLargeRange = function () {
var num = this.InternalSample();
var flag = this.InternalSample() % 2 == 0;
if (flag) {
num = -num;
}
var num2 = num;
num2 += 2147483646.0;
return num2 / 4294967293.0;
};
Random.prototype.Next = function (minValue, maxValue) {
if (!minValue && !maxValue)
return this.InternalSample();
var num = maxValue - minValue;
if (num <= 2147483647) {
return parseInt((this.Sample() * num + minValue).toFixed(0));
}
return this.GetSampleForLargeRange() * num + minValue;
};
Random.prototype.NextDouble = function () {
return this.Sample();
};
Random.prototype.NextBytes = function (buffer) {
for (var i = 0; i < buffer.length; i++) {
buffer[i] = this.InternalSample() % 256;
}
};
return Random;
}());
Posługiwać się:
var r = new Random();
var nextInt = r.Next(1, 100); //returns an integer between range
var nextDbl = r.NextDouble(); //returns a random decimal
Użyj tej funkcji, aby uzyskać losowe liczby między podanym zakresem
function rnd(min,max){
return Math.floor(Math.random()*(max-min+1)+min );
}
Po wygenerowaniu liczby losowej za pomocą programu komputerowego nadal jest uważana za liczbę losową, jeśli wybrana liczba jest częścią lub pełną liczbą początkową. Ale jeśli to się zmieniło, wówczas matematycy nie przyjmą go jako liczby losowej i mogą nazwać to liczbą stronniczą. Ale jeśli opracowujesz program do prostego zadania, nie będzie to do rozważenia. Ale jeśli opracowujesz program do generowania losowej liczby dla wartościowych rzeczy, takich jak program loteryjny lub gra hazardowa, wówczas Twój program zostanie odrzucony przez kierownictwo, jeśli nie będziesz rozważał powyższego przypadku.
Oto propozycja dla tych ludzi:
Wygeneruj liczbę losową za pomocą Math.random()
. (Powiedz to 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 squire bracket indicates that boundary is inclusive and round bracket indicates boundary is exclusive.
Then remove the rest after the decimal point. (i.e. get floor) - using Math.floor(), this can be done.
Jeśli wiesz, jak odczytać tabelę liczb losowych, aby wybrać liczbę losową, wiesz, że powyższy proces (pomnożenie przez 1, 10, 100 itd.) Nie narusza tego, o którym mówiłem na początku (ponieważ zmienia tylko miejsce przecinka dziesiętnego).
Przestudiuj poniższy przykład i opracuj go według własnych potrzeb.
Jeśli potrzebujesz próbki [0,9], to odpowiedź n * 10 jest odpowiedzią, a jeśli potrzebujesz [0,99], to odpowiedź n * 100 jest odpowiedzią i tak dalej.
Teraz wejdź w swoją rolę:
Poprosiłeś liczby z określonego zakresu. (W tym przypadku jesteś stronniczy w tym zakresie. - Biorąc liczbę z [1,6] rzucając kością, to jesteś stronniczy w [1,6], ale nadal jest losowy, jeśli i tylko jeśli kość jest bezstronna .)
Rozważ więc swój zakres ==> [78, 247] liczba elementów zakresu = 247 - 78 + 1 = 170; (ponieważ obie granice są włącznie.
/*Mthod 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);
Uwaga: W metodzie pierwszej najpierw stworzyłem tablicę zawierającą potrzebne liczby, a następnie losowo umieściłem je w innej tablicy. W metodzie drugiej generuj liczby losowo i sprawdź, czy mieszczą się w wymaganym zakresie. Następnie umieść go w tablicy. Tutaj wygenerowałem dwie liczby losowe i wykorzystałem je wszystkie, aby zmaksymalizować szybkość programu poprzez zminimalizowanie wskaźnika awaryjności w celu uzyskania użytecznej liczby. Jednak dodanie wygenerowanych liczb da również trochę stronniczości. Poleciłbym więc moją pierwszą metodę generowania liczb losowych w określonym zakresie.
W obu metodach konsola wyświetli wynik (naciśnij klawisz F12 w Chrome, aby otworzyć konsolę)
Math.floor(Math.random() * (6 - 1 + 1) + 1)
] Liczby 1 i 6 z konieczności będą walcowane mniej niż 2, 3, 4 i 5. Różnica jest jednak w zasadzie nieistotna.
Aby uzyskać losową liczbę całkowitą z zakresem, spróbuj:
function random(minimum, maximum) {
var bool = true;
while (bool) {
var number = (Math.floor(Math.random() * maximum + 1) + minimum);
if (number > 20) {
bool = true;
} else {
bool = false;
}
}
return number;
}
function getRandomInt(lower, upper)
{
//to create an even sample distribution
return Math.floor(lower + (Math.random() * (upper - lower + 1)));
//to produce an uneven sample distribution
//return Math.round(lower + (Math.random() * (upper - lower)));
//to exclude the max value from the possible values
//return Math.floor(lower + (Math.random() * (upper - lower)));
}
Aby przetestować tę funkcję i jej odmiany, zapisz poniższy kod HTML / JavaScript w pliku i otwórz w przeglądarce. Kod wygeneruje wykres pokazujący rozkład miliona wywołań funkcji. Kod zapisuje również przypadki na krawędziach, więc jeśli funkcja wygeneruje wartość większą niż maksimum lub mniejszą niż min, będziesz wiedział.
<html>
<head>
<script type="text/javascript">
function getRandomInt(lower, upper)
{
//to create an even sample distribution
return Math.floor(lower + (Math.random() * (upper - lower + 1)));
//to produce an uneven sample distribution
//return Math.round(lower + (Math.random() * (upper - lower)));
//to exclude the max value from the possible values
//return Math.floor(lower + (Math.random() * (upper - lower)));
}
var min = -5;
var max = 5;
var array = new Array();
for(var i = 0; i <= (max - min) + 2; i++) {
array.push(0);
}
for(var i = 0; i < 1000000; i++) {
var random = getRandomInt(min, max);
array[random - min + 1]++;
}
var maxSample = 0;
for(var i = 0; i < max - min; i++) {
maxSample = Math.max(maxSample, array[i]);
}
//create a bar graph to show the sample distribution
var maxHeight = 500;
for(var i = 0; i <= (max - min) + 2; i++) {
var sampleHeight = (array[i]/maxSample) * maxHeight;
document.write('<span style="display:inline-block;color:'+(sampleHeight == 0 ? 'black' : 'white')+';background-color:black;height:'+sampleHeight+'px"> [' + (i + min - 1) + ']: '+array[i]+'</span> ');
}
document.write('<hr/>');
</script>
</head>
<body>
</body>
</html>
Aby uzyskać liczbę losową, powiedzmy między 1 a 6, najpierw:
0.5 + (Math.random() * ((6 - 1) + 1))
To mnoży liczbę losową przez 6, a następnie dodaje do niej 0,5. Następnie zaokrąglij liczbę do dodatniej liczby całkowitej, wykonując:
Math.round(0.5 + (Math.random() * ((6 - 1) + 1))
Zaokrągla liczbę do najbliższej liczby całkowitej.
Aby uczynić to bardziej zrozumiałym, wykonaj następujące czynności:
var value = 0.5 + (Math.random() * ((6 - 1) + 1))
var roll = Math.round(value);
return roll;
Zasadniczo kod do wykonania tego przy użyciu zmiennych to:
var value = (Min - 0.5) + (Math.random() * ((Max - Min) + 1))
var roll = Math.round(value);
return roll;
Powodem odebrania 0,5 wartości minimalnej jest to, że samo użycie wartości minimalnej pozwoliłoby uzyskać liczbę całkowitą, która była o jeden większa od wartości maksymalnej. Odejmując 0,5 od wartości minimalnej, zasadniczo zapobiegasz zaokrąglaniu wartości maksymalnej.
Mam nadzieję, że to pomaga.
Za pomocą następującego kodu możesz wygenerować tablicę liczb losowych, bez powtarzania, w danym zakresie.
function genRandomNumber(how_many_number,min,max) {
// parameters
// how_many_number : how many numbers you want to generate. For example it is 5.
// min(inclusive) : minimum/low value of a range. it must be any positive integer but less than max. i.e 4
// max(inclusive) : maximun value of a range. it must be any positive integer. i.e 50
// return type: array
var random_number = [];
for (var i = 0; i < how_many_number; i++) {
var gen_num = parseInt((Math.random() * (max-min+1)) + min);
do {
var is_exist = random_number.indexOf(gen_num);
if (is_exist >= 0) {
gen_num = parseInt((Math.random() * (max-min+1)) + min);
}
else {
random_number.push(gen_num);
is_exist = -2;
}
}
while (is_exist > -1);
}
document.getElementById('box').innerHTML = random_number;
}
Wiem, że na to pytanie już udzielono odpowiedzi, ale moja odpowiedź może komuś pomóc.
Znalazłem tę prostą metodę na W3Schools:
Math.floor((Math.random() * max) + min);
Mam nadzieję, że to komuś pomoże.
Losowa liczba całkowita od najniższej do najwyższej:
function randomRange(l,h){
var range = (h-l);
var random = Math.floor(Math.random()*range);
if (random === 0){random+=1;}
return l+random;
}
Nie jest to najbardziej eleganckie rozwiązanie ... ale coś szybkiego.
Oto, czego używam do generowania liczb losowych.
function random(high,low) {
high++;
return Math.floor((Math.random())*(high-low))+low;
}
Wykonujemy, high++
ponieważ Math.random()
generuje losową liczbę od 0 (włącznie) i 1 (wyłącznie) Ta wykluczona oznacza, że musimy zwiększyć najwyższą wartość o jeden przed wykonaniem jakiejkolwiek matematyki. Następnie odejmujemy niski od wysokiego, dając nam najwyższą liczbę do wygenerowania - niską, a następnie + niską, przywracając wysoką wartość z powrotem do normalnej, a najniższą liczbę co najmniej najniższą. następnie zwracamy wynikową liczbę
random(7,3)
może wrócić 3,4,5,6, or 7
high
jest używany tylko raz, równie dobrze możesz użyć high-low+1
zamiast osobnej instrukcji przyrostu. Ponadto większość użytkowników spodziewałaby się, że low
parametr będzie na pierwszym miejscu.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<script>
/*
assuming that window.crypto.getRandomValues is available
the real range would be fron 0 to 1,998 instead of 0 to 2,000
See javascript documentation for explanation
https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues
*/
var array = new Uint8Array(2);
window.crypto.getRandomValues(array);
console.log(array[0] + array[1]);
</script>
</body>
</html>
Uint8Array tworzy tablicę wypełnioną liczbą do 3 cyfr, która może wynosić maksymalnie 999. Ten kod jest bardzo krótki.
Oto przykład funkcji javascript, która może generować losową liczbę o dowolnej określonej długości bez użycia 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;
}
to jest moje zdanie na temat liczby losowej w zakresie, ponieważ chciałem uzyskać liczbę losową w zakresie od podstawy do wykładnika. np. podstawa = 10, wykładnik = 2, daje liczbę losową od 0 do 100, idealnie itd.
jeśli to pomaga w użyciu, oto:
// get random number within provided base + exponent
// by Goran Biljetina --> 2012
function isEmpty(value){
return (typeof value === "undefined" || value === null);
}
var numSeq = new Array();
function add(num,seq){
var toAdd = new Object();
toAdd.num = num;
toAdd.seq = seq;
numSeq[numSeq.length] = toAdd;
}
function fillNumSeq (num,seq){
var n;
for(i=0;i<=seq;i++){
n = Math.pow(num,i);
add(n,i);
}
}
function getRandNum(base,exp){
if (isEmpty(base)){
console.log("Specify value for base parameter");
}
if (isEmpty(exp)){
console.log("Specify value for exponent parameter");
}
fillNumSeq(base,exp);
var emax;
var eseq;
var nseed;
var nspan;
emax = (numSeq.length);
eseq = Math.floor(Math.random()*emax)+1;
nseed = numSeq[eseq].num;
nspan = Math.floor((Math.random())*(Math.random()*nseed))+1;
return Math.floor(Math.random()*nspan)+1;
}
console.log(getRandNum(10,20),numSeq);
//testing:
//getRandNum(-10,20);
//console.log(getRandNum(-10,20),numSeq);
//console.log(numSeq);
Math.random()
jest szybki i odpowiedni do wielu celów, ale nie jest odpowiedni, jeśli potrzebujesz bezpiecznych kryptograficznie wartości (nie jest bezpieczny) lub jeśli potrzebujesz liczb całkowitych z całkowicie jednorodnego rozkładu bezstronnego (metoda mnożenia stosowana w innych odpowiedziach nieco częściej wytwarza określone wartości niż inni).
W takich przypadkach możemy użyć crypto.getRandomValues()
do wygenerowania bezpiecznych liczb całkowitych i odrzucić wszelkie wygenerowane wartości, których nie możemy jednolicie odwzorować w zakresie docelowym. Będzie to wolniejsze, ale nie powinno być znaczące, chyba że generujesz wyjątkowo dużą liczbę wartości.
Aby wyjaśnić problem z tendencyjnym rozkładem, rozważ przypadek, w którym chcemy wygenerować wartość między 1 a 5, ale mamy generator liczb losowych, który wytwarza wartości między 1 a 16 (wartość 4-bitowa). Chcemy, aby ta sama liczba wygenerowanych wartości została odwzorowana na każdą wartość wyjściową, ale 16 nie dzieli się równomiernie przez 5: pozostawia pozostałą część 1. Musimy więc odrzucić 1 z możliwych wygenerowanych wartości i kontynuować tylko, gdy otrzymamy jedna z 15 mniejszych wartości, które mogą być jednolicie odwzorowane w naszym zakresie docelowym. Nasze zachowanie może wyglądać następująco:
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.
Poniższy kod wykorzystuje podobną logikę, ale generuje 32-bitową liczbę całkowitą, ponieważ jest to największy wspólny rozmiar liczby całkowitej, który może być reprezentowany przez standardowy number
typ JavaScript . (Można to zmienić, aby użyć BigInt
s, jeśli potrzebujesz większego zakresu.) Niezależnie od wybranego zakresu, część wygenerowanych wartości, które są odrzucane, zawsze będzie mniejsza niż 0,5, więc oczekiwana liczba odrzuceń będzie zawsze mniejsza niż 1,0 i zwykle blisko 0,0; nie musisz się martwić, że zapętli się na zawsze.
const randomInteger = (min, max) => {
const range = max - min;
const maxGeneratedValue = 0xFFFFFFFF;
const possibleResultValues = range + 1;
const possibleGeneratedValues = maxGeneratedValue + 1;
const remainder = possibleGeneratedValues % possibleResultValues;
const maxUnbiased = maxGeneratedValue - remainder;
if (!Number.isInteger(min) || !Number.isInteger(max) ||
max > Number.MAX_SAFE_INTEGER || min < Number.MIN_SAFE_INTEGER) {
throw new Error('Arguments must be safe integers.');
} else if (range > maxGeneratedValue) {
throw new Error(`Range of ${range} (from ${min} to ${max}) > ${maxGeneratedValue}.`);
} else if (max < min) {
throw new Error(`max (${max}) must be >= min (${min}).`);
} else if (min === max) {
return min;
}
let generated;
do {
generated = crypto.getRandomValues(new Uint32Array(1))[0];
} while (generated > maxUnbiased);
return min + (generated % possibleResultValues);
};
console.log(randomInteger(-8, 8)); // -2
console.log(randomInteger(0, 0)); // 0
console.log(randomInteger(0, 0xFFFFFFFF)); // 944450079
console.log(randomInteger(-1, 0xFFFFFFFF));
// Error: Range of 4294967296 covering -1 to 4294967295 is > 4294967295.
console.log(new Array(12).fill().map(n => randomInteger(8, 12)));
// [11, 8, 8, 11, 10, 8, 8, 12, 12, 12, 9, 9]
Aby uzyskać krypto-silną losową liczbę całkowitą w ragne [x, y] spróbuj
let cs= (x,y)=>x+(y-x+1)*crypto.getRandomValues(new Uint32Array(1))[0]/2**32|0
console.log(cs(4,8))
Możesz zrobić ten fragment kodu,
let randomNumber = function(first,second){
let number = Math.floor(Math.random()*Math.floor(second));
while(number<first){
number = Math.floor(Math.random()*Math.floor(second));
}
return number;
}
do - while
zamiastwhile
Ionuț G. Stan napisał świetną odpowiedź, ale było to dla mnie zbyt skomplikowane. Znalazłem więc jeszcze prostsze wyjaśnienie tych samych pojęć na https://teamtreehouse.com/community/mathfloor-mathrandom-max-min-1-min-explanation przez Jasona Anello.
UWAGA: Jedyną ważną rzeczą, którą powinieneś wiedzieć przed przeczytaniem wyjaśnień Jasona, jest definicja „obcięcia”. Używa tego terminu przy opisywaniu Math.floor()
. Słownik Oxford definiuje „obcinać” jako:
Skróć (coś), odcinając górę lub koniec.
Może to obsłużyć generowanie do 20 cyfr niepowtarzalnej liczby losowej
JS
var generatedNumbers = [];
function generateRandomNumber(precision) { // precision --> number precision in integer
if (precision <= 20) {
var randomNum = Math.round(Math.random().toFixed(precision) * Math.pow(10, precision));
if (generatedNumbers.indexOf(randomNum) > -1) {
if (generatedNumbers.length == Math.pow(10, precision))
return "Generated all values with this precision";
return generateRandomNumber(precision);
} else {
generatedNumbers.push(randomNum);
return randomNum;
}
} else
return "Number Precision shoould not exceed 20";
}
generateRandomNumber(1);
/ * Napisz wywoływaną funkcję, randUpTo
która akceptuje liczbę i zwraca losową liczbę całkowitą od 0 do tej liczby? * /
var randUpTo = function(num) {
return Math.floor(Math.random() * (num - 1) + 0);
};
/ * Napisz nazwaną funkcję, randBetween
która akceptuje dwie liczby reprezentujące zakres i zwraca losową liczbę całkowitą między tymi dwiema liczbami. * /
var randBetween = function (min, max) {
return Math.floor(Math.random() * (max - min - 1)) + min;
};
/ * Napisz wywoływaną funkcję, randFromTill
która akceptuje dwie liczby reprezentujące zakres i zwraca liczbę losową między min (włącznie) i max (wyłącznie). * /
var randFromTill = function (min, max) {
return Math.random() * (max - min) + min;
};
/ * Napisz wywoływaną funkcję, randFromTo
która akceptuje dwie liczby reprezentujące zakres i zwraca losową liczbę całkowitą między min (włącznie) i max (włącznie) * /
var randFromTo = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
Zrobiłem tę funkcję, która bierze pod uwagę opcje takie jak min, max, exclude (lista ints do wykluczenia) i seed (na wypadek, gdybyś chciał rozstawionego generatora losowego).
get_random_int = function(args={})
{
let def_args =
{
min: 0,
max: 1,
exclude: false,
seed: Math.random
}
args = Object.assign(def_args, args)
let num = Math.floor(args.seed() * (args.max - args.min + 1) + args.min)
if(args.exclude)
{
let diff = args.max - args.min
let n = num
for(let i=0; i<diff*2; i++)
{
if(args.exclude.includes(n))
{
if(n + 1 <= args.max)
{
n += 1
}
else
{
n = args.min
}
}
else
{
num = n
break
}
}
}
return num
}
Może być używany jak:
let n = get_random_int
(
{
min: 0,
max: some_list.length - 1,
exclude: [3, 6, 5],
seed: my_seed_function
}
)
Lub prościej:
let n = get_random_int
(
{
min: 0,
max: some_list.length - 1
}
)
Następnie możesz zrobić:
let item = some_list[n]
Gist: https://gist.github.com/madprops/757deb000bdec25776d5036dae58ee6e
Math.floor zaokrągla liczbę w dół do najbliższej liczby całkowitej
function generateRandomInteger (min, max) {
return Math.floor(random(min,max))
}`
Aby więc wygenerować losową liczbę całkowitą od 4 do 8 włącznie, wywołaj powyższą funkcję z następującymi argumentami:
generateRandomInteger (4,9)
Moja metoda generowania liczb losowych od 0 do n, gdzie n <= 10 (n wykluczone):
Math.floor((Math.random() * 10) % n)