Wygeneruj losową liczbę między dwiema liczbami w JavaScript

1795

Czy istnieje sposób na wygenerowanie liczby losowej w określonym zakresie (np. Od 1 do 6: 1, 2, 3, 4, 5 lub 6) w JavaScript?

Mirgorod
źródło
12
Math.floor (Math.random () * 7)
Amjad Masad
65
Jasne .. Math.floor (Math.random () * 6 + 1)
Amjad Masad
3
Nabil Kadimi napisał również artykuł na temat generowania ujemnych liczb losowych .
madc
oto przydatna treść: gist.github.com/kerimdzhanov/7529623
Dan KK,
dlaczego takie rozwiązanie Math.floor((Math.random()*10)+1);nie może dla Ciebie działać, jak określono tutaj na w3schools.com/jsref/jsref_random.asp ..?
shashwat

Odpowiedzi:

2115

Ważny

Poniższy kod działa tylko wtedy, gdy minimalna wartość to 1. Nie działa dla wartości minimalnych innych niż 1.

Jeśli chcesz uzyskać losową liczbę całkowitą od 1 ( i tylko 1 ) do 6, obliczysz:

Math.floor(Math.random() * 6) + 1  

Gdzie:

  • 1 to numer początkowy
  • 6 to liczba możliwych wyników (1 + początek (6) - koniec (1) )
khr055
źródło
45
Chociaż to zadziała, @Mike, najlepiej wskazać bardziej ogólną wersję, ponieważ Francisc ma ją poniżej :-).
Raymond Machira
58
-1. Po Googlingu znalazłem to pytanie, tytuł brzmi „„ Wygeneruj losową wartość między dwiema liczbami w JavaScript ”.” Nie zadziała, jeśli minimalna wartość to 0
Ydhem
18
Nie działa, jeśli chcesz liczbę między dwiema większymi liczbami, np. Math.floor (Math.random () * 900) + 700
Rob
14
Działa to tylko wtedy, gdy minimum wynosi 1. Jeśli min wynosi 2, a nadal używamy, Math.floor(Math.random() * 6) + 2oznacza to, że jeśli Math.random()wyniki w 0.99, nasza losowa wartość będzie7
antytoksyczna
27
Ten kod nie jest dobry, ponieważ nie działa z żadną liczbą. Kod @Francisc jest poprawny.
Król Lew
2283
function randomIntFromInterval(min, max) { // min and max included 
  return Math.floor(Math.random() * (max - min + 1) + min);
}

To, co robi „dodatkowe”, to pozwala na losowe interwały, które nie zaczynają się od 1. W ten sposób można na przykład uzyskać losową liczbę od 10 do 15. Elastyczność.

Franciszek
źródło
5
jest to również świetne, ponieważ jeśli ktoś nie zawiera toargumentu, fromargument podwaja się jako maksimum
Jason
12
Witaj. Pochodzi z MDN: Returns a floating-point, pseudo-random number in the range [0, 1) that is, from 0 (inclusive) up to but not including 1 (exclusive), which you can then scale to your desired range.( developer.mozilla.org/en-US/docs/JavaScript/Reference/… )
Francisc
5
Przeczytaj powyższy komentarz. Losowy jest w środku [0,1), a nie [0,1].
Francisc
3
Działa świetnie, jeśli niższa liczba to 0.
Robin Zimmermann
2
Zauważ, że to rozwiązanie jest poprawne tylko wtedy, gdy min i max są liczbami całkowitymi, w przeciwnym razie możesz uzyskać wynik w przedziale [min, pułap (maks.)]. Czyli możesz uzyskać wynik, który jest poza zakresem, ponieważ jest wyższy niż maks.
collimarco
326

Math.random ()

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 ​​().

Lior Elrom
źródło
Coś, co mnie pomyliło ... Math.floor (..) zapewnia, że ​​liczba jest liczbą całkowitą, w której Math.round (..) dałby nierówny rozkład. Ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
alikuli
1
Ufam tej odpowiedzi. Czy ktoś może podać link lub jasne wyjaśnienie, dlaczego to działa? Być może przykład tego, jak Math.round dałby stronniczość i dlaczego to oznacza, że ​​musimy użyć tej raczej złożonej pozornie formuły?
Robin Andrews,
6
@alikuli Dla wielu [1,2], istnieje 25% szansy Math.random()nie daje liczbę od jednego z nich [0,0.49], [0.5,0.99], [1,1.49], [1.5,1.99]. Zaokrąglenie tych przedziałów spowodowałoby 0, 1, 1, 2, co nie jest równomiernym rozkładem.
Posadzenie ich na podłodze
1
@shuji Jest to między innymi poprawna odpowiedź. Chciałem tylko wyjaśnić, dlaczego Math.roundnadmierne używanie Math.floordaje różne wyniki.
pishpish
Najdokładniejsze rozwiązanie, jakie znalazłem: function getRandomInt(min, max) { return Math.round((min - 0.5) + Math.random() * (max - min + 1)); }
Sadik
91

Inne rozwiązania:

  • (Math.random() * 6 | 0) + 1
  • ~~(Math.random() * 6) + 1

Wypróbuj online

Vishal
źródło
6
czy mógłbyś wyjaśnić (lub podać odniesienia) ~ ~ sintaksję? Nie widziałem tego wcześniej! Eleganckie rozwiązanie, ale trudne do zrozumienia.
DiegoDD
27
Podwójna tylda ~~a i bitowe OR (a | 0) są szybszymi sposobami pisania Math.floor (a)
edi9999
7
a | 0jest także najszybszym i najbardziej zoptymalizowanym sposobem konwersji łańcucha na liczbę całkowitą. Działa tylko z łańcuchami zawierającymi liczby całkowite ( "444"i "-444"), tj. Bez pływaków / ułamków. Daje a 0za wszystko, co zawiedzie. Jest to jedna z głównych optymalizacji asm.js.
pilau
3
Uwaga: jeśli pracujesz z naprawdę dużymi liczbami, podwójna tylda nie zadziała. Spróbuj ~~(Math.random() * (50000000000000 - 0 + 1)) + 0iMath.floor(Math.random() * (50000000000000 - 0 + 1)) + 0
BrunoLM,
3
„Podwójna tylda i bitowe OR / są szybszymi sposobami na pisanie matematyki na podłodze” to piękny rymowany kuplet, który rozjaśnił mój poranek. Dzięki @ edi9999!
teedyay
60

TL; DR

function generateRandomInteger(min, max) {
  return Math.floor(min + Math.random()*(max + 1 - min))
}

Aby uzyskać liczbę losową generateRandomInteger(-20, 20);

WYJAŚNIENIE PONIŻEJ

Musimy uzyskać losową liczbę całkowitą, powiedzmy X między min a max.

Dobrze?

tj. min <= X <= maks

Jeśli odejmiemy min od równania, jest to równoważne z

0 <= (X - min) <= (maks. - min)

Teraz pomnóżmy to przez losową liczbę r, która jest

0 <= (X - min) * r <= (max - min) * r

Teraz dodajmy z powrotem min do równania

min <= min + (X - min) * r <= min + (max - min) * r

Teraz, pozwala wybrał funkcję, która powoduje R w taki sposób, że spełnia równanie jako zakres naszego [min, X, max]. Jest to możliwe tylko wtedy, gdy 0 <= r <= 1

OK. Teraz zakres r ie [0,1] jest bardzo podobny do wyniku funkcji Math.random (). Czyż nie

Funkcja Math.random () zwraca liczbę zmiennoprzecinkową, pseudolosową w zakresie [0, 1); to znaczy od 0 (włącznie) do, ale nie wliczając 1 (wyłącznie)

Na przykład,

Przypadek r = 0

min+ 0 * ( max- min) = min

Przypadek r = 1

min+ 1 * ( max- min) = maks

Przypadek losowy przy użyciu Math.random 0 <= r <1

min+ r * ( max- min) = X , gdzie X ma zakres min <= X < maks

Powyższy wynik X jest losową liczbą. Jednak ze względu na Math.random () nasza lewa granica jest włączająca, a prawa granica jest wyłączna. Aby uwzględnić naszą prawą granicę, zwiększamy prawą granicę o 1 i podnosimy wynik.

function generateRandomInteger(min, max) {
  return Math.floor(min + Math.random()*(max + 1 - min))
}

Aby uzyskać liczbę losową

generateRandomInteger(-20, 20);

Faiz Mohamed Haneef
źródło
25

Lub w podkreśleniu

_.random(min, max)
Vladiim
źródło
24
var x = 6; // can be any number
var rand = Math.floor(Math.random()*x) + 1;
ryebr3ad
źródło
2
W rzeczy samej. Zapomniałem, że rand miał 0 włącznie. Naprawione.
ryebr3ad
3
To część Pseudokodu ... ktoś może pomyśleć, że to prawda i spróbować go użyć w ten sposób.
gravityboy
35
@gravityboy O czym ty mówisz? Jeśli ktoś nie może zastąpić numeru [wybierz numer ...], może nie być odpowiednim programistą.
ryebr3ad
7
@ ryebr3ad -1! jest napisane w javascript, a nie w pseudokodzie, a także nie wszyscy czytelnicy są doświadczonymi programistami. Wielu jest początkującymi!
Steve
3
@ ryebr3ad: Miałem współpracownika, który uczył stażystów na temat środowiska baz danych, którego potrzebują wsparcia. Powiedział im, aby wybrali wszystko z tabeli, a oni zaczęli pisać „wybierz wszystko z ...” bezpośrednio w edytorze zapytań SQL. Miał taką samą reakcję jak ty.
Ellesedil
22

jsfiddle: https://jsfiddle.net/cyGwf/477/

Random Integer : aby uzyskać losową liczbę całkowitą pomiędzy mini max, użyj następującego kodu

function getRandomInteger(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min)) + min;
}

Losowy numer zmiennoprzecinkowy : aby uzyskać losową liczbę zmiennoprzecinkową między mini max, użyj następującego kodu

function getRandomFloat(min, max) {
  return Math.random() * (max - min) + min;
}

Odniesienie: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random

Razan Paul
źródło
14

Matematyka nie jest moją mocną stroną, ale pracowałem nad projektem, w którym musiałem wygenerować wiele liczb losowych między zarówno dodatnimi, jak i ujemnymi.

function randomBetween(min, max) {
    if (min < 0) {
        return min + Math.random() * (Math.abs(min)+max);
    }else {
        return min + Math.random() * max;
    }
}

Na przykład

randomBetween(-10,15)//or..
randomBetween(10,20)//or...
randomBetween(-200,-100)

Oczywiście możesz także dodać sprawdzanie poprawności, aby upewnić się, że nie robisz tego z niczym innym niż liczbami. Upewnij się również, że min jest zawsze mniejsze lub równe max.

Petter Thowsen
źródło
5
To jest po prostu złe. min + Math.random() * maxda ci liczby od min do min + max, co nie jest tym, czego chcesz. Pierwsza gałąź tej ifjest poprawna, ale można ją uprościć, mówiąc return min + Math.random() * (max - min), która jest poprawnym rozwiązaniem niezależnie od tego, czy min jest dodatnia czy ujemna (patrz pozostałe odpowiedzi). Pamiętaj też, że jeśli nie chcesz ułamków, nadal musisz obniżyć wynik.
Avish
10

Napisałem bardziej elastyczną funkcję, która może dać ci liczbę losową, ale nie tylko liczbę całkowitą.

function rand(min,max,interval)
{
    if (typeof(interval)==='undefined') interval = 1;
    var r = Math.floor(Math.random()*(max-min+interval)/interval);
    return r*interval+min;
}

var a = rand(0,10); //can be 0, 1, 2 (...) 9, 10
var b = rand(4,6,0.1); //can be 4.0, 4.1, 4.2 (...) 5.9, 6.0

Naprawiona wersja.

ElChupacabra
źródło
To nie jest dobre rozwiązanie, ponieważ nie będzie działać przy zerowej wartości minimalnej. Zobacz odpowiedź @ Lior.
Sebastien
Oczywiście działa z wartością zerową jako wartością minimalną. Próbowałeś? Nie ma powodu, dla którego może nie działać. Nie będzie działać z 0 jako interwałem, co nie jest dziwne (interwał = 0? ...).
ElChupacabra
Uruchomiłem tę funkcję wiele razy z zerową wartością minimalną i nigdy nie uzyskałem zera na wyjściu. Albo nie mam szczęścia ...
Sebastien
Masz rację. „+ interwał” był w niewłaściwym miejscu. Przetestuj teraz, proszę. Dziwna rzecz, która czasami console.log daje mi 0.300000004 zamiast 0.3 jak 3 * 0.1 nie byłoby dokładnie 0.3.
ElChupacabra,
9

Przykład

Zwróć losową liczbę od 1 do 10:

Math.floor((Math.random() * 10) + 1);

Wynik może być: 3

Spróbuj sam: tutaj

-

lub używając lodash / undescore:

_.random(min, max)

Dokumenty: - lodash - undescore

Sebastián Lara
źródło
1
więc potrzebujesz 9 lub 10, prawda? Jeśli tak: const randomNumber = Math.floor ((Math.random () * 10) + 1) const nineOrTen = randomNumber% 2 === 0? 9: 10
Sebastián Lara,
7

Pomimo wielu odpowiedzi i prawie tego samego rezultatu. Chciałbym dodać swoją odpowiedź i wyjaśnić jej działanie. Ponieważ ważne jest, aby zrozumieć jego działanie, a nie kopiować wklejanie kodu jednego wiersza. Generowanie liczb losowych to nic innego jak prosta matematyka.

KOD:

function getR(lower, upper) {

  var percent = (Math.random() * 100);
  // this will return number between 0-99 because Math.random returns decimal number from 0-0.9929292 something like that
  //now you have a percentage, use it find out the number between your INTERVAL :upper-lower 
  var num = ((percent * (upper - lower) / 100));
  //num will now have a number that falls in your INTERVAL simple maths
  num += lower;
  //add lower to make it fall in your INTERVAL
  //but num is still in decimal
  //use Math.floor>downward to its nearest integer you won't get upper value ever
  //use Math.ceil>upward to its nearest integer upper value is possible
  //Math.round>to its nearest integer 2.4>2 2.5>3   both lower and upper value possible
  console.log(Math.floor(num), Math.ceil(num), Math.round(num));
}
Arun Sharma
źródło
6

Szukałem generatora liczb losowych napisanego w TypeScript i napisałem to po przeczytaniu wszystkich odpowiedzi, mam nadzieję, że zadziała dla koderów TypeScript.

    Rand(min: number, max: number): number {
        return (Math.random() * (max - min + 1) | 0) + min;
    }   
Erdi İzgi
źródło
5

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 numbertyp JavaScript . (Można to zmienić, aby użyć BigInts, 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]

Jeremy Banks
źródło
To właśnie nazywam przesadą.
2xSamurai
2
@ 2xSamurai Tam zaktualizowałem odpowiedź, aby wyjaśnić, dlaczego możesz tego potrzebować i jak to działa. Czy to jest lepsze? : P
Jeremy Banks,
Nie jest to przesada, jeśli chcesz kryptograficznie bezpieczne i równomiernie rozmieszczone losowe liczby. Generowanie liczb losowych spełniających te wymagania jest trudne. Świetna odpowiedź, @JeremyBanks.
thomaskonrad,
4

Dodawanie floatze stałą precyzją w oparciu o intwersję z odpowiedzi @ Francisc:

function randomFloatFromInterval (min, max, fractionDigits) {
  const fractionMultiplier = Math.pow(10, fractionDigits)
  return Math.round(
    (Math.random() * (max - min) + min) * fractionMultiplier,
  ) / fractionMultiplier
}

więc:

randomFloatFromInterval(1,3,4) // => 2.2679, 1.509, 1.8863, 2.9741, ...

i dla int odpowiedzi

randomFloatFromInterval(1,3,0) // => 1, 2, 3
yonatanmn
źródło
3

Krypto-silna losowa liczba całkowita z zakresu [a, b] (założenie: a <b)

let rand= (a,b)=> a+(b-a+1)*crypto.getRandomValues(new Uint32Array(1))[0]/2**32|0

console.log( rand(1,6) );

Kamil Kiełczewski
źródło
1

To powinno działać:

const getRandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min
sbr_amd
źródło
1

Odkryłem świetny nowy sposób na wykonanie tego przy użyciu domyślnych parametrów ES6. Jest bardzo fajny, ponieważ pozwala na jeden argument lub dwa argumenty. Oto on:

function random(n, b = 0) {
    return Math.random() * (b-n) + n;
}
maburdi94
źródło
1

Spóźnia się to około dziewięciu lat, ale randojs.com sprawia, że ​​jest to prosta liniówka :

rando(1, 6)

Musisz tylko dodać to do nagłówka dokumentu HTML, a możesz z łatwością robić dowolne rzeczy z przypadkiem. Losowe wartości z tablic, losowe elementy jquery, losowe właściwości z obiektów, a nawet zapobieganie powtórzeniom w razie potrzeby.

<script src="https://randojs.com/1.0.0.js"></script>
Aaron Plocharczyk
źródło
Po co dodawać zależność, aby zrobić coś, co już jest liniowe? Obsesja na punkcie dodawania bibliotek w społeczności JS jest szalona
Daniel Cooke
łatwiejsze do odczytania i zapamiętania. zgadzam się jednak
Aaron Plocharczyk,
1

Działa to dla mnie i generuje wartości takie jak standardowa funkcja biblioteki random.randint w Pythonie :


function randint(min, max) {
   return Math.round((Math.random() * Math.abs(max - min)) + min);
}

console.log("Random integer: " + randint(-5, 5));
gnrfan
źródło
1

Spróbuj użyć:

function random(min, max) {
   return Math.round((Math.random() *( Math.abs(max - min))) + min);
}
console.log(random(1, 6));

AyushKatiyar
źródło
1

zwracać 1-6 jak kostka w zasadzie,

return Math.round(Math.random() * 5 + 1);
Husky931
źródło