Hasilkan nomor acak antara dua angka dalam JavaScript

1798

Apakah ada cara untuk menghasilkan angka acak dalam rentang yang ditentukan (misalnya dari 1 hingga 6: 1, 2, 3, 4, 5, atau 6) dalam JavaScript?

Mirgorod
sumber
12
Math.floor (Math.random () * 7)
Amjad Masad
65
Tentu .. Math.floor (Math.random () * 6 +1)
Amjad Masad
3
Nabil Kadimi menulis artikel tentang cara menghasilkan angka acak negatif juga.
madc
di sini adalah intisari yang berguna: gist.github.com/kerimdzhanov/7529623
Dan KK
mengapa solusi seperti ini Math.floor((Math.random()*10)+1);tidak dapat bekerja untuk Anda seperti yang ditentukan di sini di w3schools.com/jsref/jsref_random.asp ..?
shashwat

Jawaban:

2118

Penting

Kode berikut hanya berfungsi jika nilai minimumnya adalah 1. Itu tidak bekerja untuk nilai minimum selain 1.

Jika Anda ingin mendapatkan bilangan bulat acak antara 1 ( dan hanya 1 ) dan 6, Anda akan menghitung:

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

Dimana:

  • 1 adalah angka awal
  • 6 adalah jumlah hasil yang mungkin (1 + mulai (6) - akhir (1) )
khr055
sumber
45
Meskipun ini akan berhasil, @Mike, yang terbaik adalah menunjukkan versi yang lebih umum seperti yang Francisc miliki di bawah ini :-).
Raymond Machira
59
-1. Setelah Googling saya menemukan pertanyaan ini judulnya adalah "" Hasilkan nilai acak antara dua angka dalam Javascript "." Tidak akan berfungsi jika nilai min adalah 0
Ydhem
18
Tidak berfungsi jika Anda menginginkan angka antara dua angka yang lebih besar misalnya. Math.floor (Math.random () * 900) + 700
Rob
15
Itu hanya bekerja jika minimum adalah 1. Jika min adalah 2 dan kami masih menggunakan Math.floor(Math.random() * 6) + 2berarti bahwa jika Math.random()hasil menjadi 0.99 nilai acak kami akan menjadi7
antitoxic
28
Kode ini tidak baik karena, tidak berfungsi dengan angka apa pun. @Francisc code adalah yang benar.
Lion King
2287
function randomIntFromInterval(min, max) { // min and max included 
  return Math.floor(Math.random() * (max - min + 1) + min);
}

Apa yang ia lakukan "ekstra" adalah itu memungkinkan interval acak yang tidak dimulai dengan 1. Jadi Anda bisa mendapatkan nomor acak dari 10 hingga 15 misalnya. Fleksibilitas.

Francisc
sumber
5
ini juga bagus karena jika seseorang tidak memasukkan toarg, fromarg berfungsi ganda sebagai max
Jason
12
Halo. Ini dari 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
Baca komentar di atas. Acak ada di dalam [0,1), bukan [0,1].
Francisc
3
Bekerja dengan baik jika angka yang lebih rendah adalah 0.
Robin Zimmermann
2
Perhatikan bahwa solusi ini benar hanya jika min dan maks adalah bilangan bulat, jika tidak, Anda bisa mendapatkan hasil dalam interval [min, ceil (max)]. Yaitu Anda bisa mendapatkan hasil yang di luar jangkauan karena lebih tinggi dari maks.
collimarco
329

Math.random ()

Mengembalikan angka acak bilangan bulat antara min ( termasuk ) dan maks ( termasuk ):

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

Atau angka acak antara min ( termasuk ) dan maks ( tidak termasuk ):

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

Contoh berguna (bilangan bulat):

// 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;

** Dan selalu senang diingatkan (Mozilla):

Math.random () tidak memberikan nomor acak yang aman secara kriptografis. Jangan menggunakannya untuk apa pun yang terkait dengan keamanan. Gunakan API Crypto Web sebagai gantinya, dan lebih tepatnya metode window.crypto.getRandomValues ​​().

Lior Elrom
sumber
Sesuatu yang membingungkan saya ... the Math.floor (..) memastikan bahwa angka tersebut adalah bilangan bulat di mana Math.round (..) akan memberikan distribusi yang tidak merata. Ref: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
alikuli
1
Saya percaya jawaban ini. Adakah yang bisa memberikan tautan atau penjelasan yang jelas tentang mengapa ini berhasil? Mungkin contoh bagaimana Math.round akan memberikan bias, dan mengapa itu berarti kita harus menggunakan formula yang agak rumit ini?
Robin Andrews
6
@alikuli Untuk berbagai [1,2], ada 25% kemungkinan Math.random()akan memberikan nomor dari salah satu [0,0.49], [0.5,0.99], [1,1.49], [1.5,1.99]. Membulatkan interval tersebut akan menghasilkan 0, 1, 1, 2 yang bukan distribusi genap. Flooring mereka menghasilkan 0, 0, 1, 1.
pishpish
1
@shuji ini adalah , antara lain, jawaban yang benar. Saya hanya ingin menjelaskan mengapa menggunakan Math.roundlebih dari itu Math.floorakan memberikan hasil yang berbeda.
pishpish
Solusi paling akurat yang saya temukan: function getRandomInt(min, max) { return Math.round((min - 0.5) + Math.random() * (max - min + 1)); }
Sadik
91

Solusi lain:

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

Coba online

Vishal
sumber
6
maukah Anda menjelaskan (atau memberikan referensi) pada ~~ sintaxis? Saya belum pernah melihatnya sebelumnya! Solusi elegan tapi sulit dimengerti.
DiegoDD
27
Double Tilde ~~a dan Bitwise OR (a | 0) adalah cara yang lebih cepat untuk menulis Math.floor (a)
edi9999
7
a | 0juga merupakan cara tercepat dan paling optimal untuk mengkonversi string ke integer. Ini hanya bekerja dengan string yang berisi bilangan bulat ( "444"dan "-444"), yaitu tidak ada float / fraksi. Ini menghasilkan 0untuk semua yang gagal. Ini adalah salah satu optimasi utama di balik asm.js.
pilau
3
Catatan: jika Anda bekerja dengan angka yang sangat besar, tilde ganda tidak akan berfungsi. Coba ~~(Math.random() * (50000000000000 - 0 + 1)) + 0danMath.floor(Math.random() * (50000000000000 - 0 + 1)) + 0
BrunoLM
3
"Double tilde dan bitwise ATAU / adalah cara yang lebih cepat untuk menulis Math dot floor" adalah bait sajak yang indah yang mencerahkan pagi saya. Terima kasih @ edi9999!
teedyay
60

TL; DR

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

Untuk mendapatkan nomor acak generateRandomInteger(-20, 20);

PENJELASAN DI BAWAH INI

Kita perlu mendapatkan integer acak, misalkan X antara min dan maks.

Baik?

yaitu min <= X <= maks

Jika kita mengurangi min dari persamaan, ini sama dengan

0 <= (X - mnt) <= (Maks - mnt)

Sekarang, mari kita gandakan ini dengan angka acak r yang

0 <= (X - mnt) * r <= (maks - mnt) * r

Sekarang, mari tambahkan kembali min ke persamaan

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

Sekarang, mari kita pilih fungsi yang menghasilkan r sehingga memenuhi rentang persamaan kita sebagai [min, maks]. Ini hanya mungkin jika 0 <= r <= 1

BAIK. Sekarang, kisaran r yaitu [0,1] sangat mirip dengan hasil fungsi Math.random (). Bukan?

Fungsi Math.random () mengembalikan angka floating-point, pseudo-random dalam rentang [0, 1); yaitu, dari 0 (inklusif) hingga tetapi tidak termasuk 1 (eksklusif)

Sebagai contoh,

Kasus r = 0

min+ 0 * ( max- min) = mnt

Kasus r = 1

min+1 * ( max- min) = maks

Kasus Acak menggunakan Math.random 0 <= r <1

min+ r * ( max- min) = X , di mana X memiliki rentang min <= X < maks

Hasil di atas X adalah angka acak. Namun karena Math.random () batas kiri kami inklusif, dan batas kanan eksklusif. Untuk memasukkan batas kanan kami, kami menambah batas kanan 1 dan lantai hasilnya.

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

Untuk mendapatkan nomor acak

generateRandomInteger(-20, 20);

Faiz Mohamed Haneef
sumber
25

Atau, dalam Garis Bawah

_.random(min, max)
vladiim
sumber
24
var x = 6; // can be any number
var rand = Math.floor(Math.random()*x) + 1;
ryebr3ad
sumber
2
Memang. Saya lupa rand 0 inklusif. Memperbaikinya.
ryebr3ad
3
Itu bagian Pseudocode ... seseorang mungkin berpikir itu nyata dan mencoba menggunakannya seperti itu.
gravityboy
35
@gravityboy Apa yang kamu bicarakan? Jika seseorang tidak dapat mengganti nomor untuk [pilih nomor ...], mereka mungkin tidak cocok sebagai programmer.
ryebr3ad
7
@ ryebr3ad -1! dikatakan dalam javascript tidak dalam kode pseudo dan juga tidak semua pembaca adalah programmer yang pandai. Banyak yang pemula!
Steve
3
@ ryebr3ad: Saya memiliki rekan kerja yang mengajar karyawan magang tentang lingkungan basis data yang mereka perlukan dukungan. Dia mengatakan kepada mereka untuk memilih semuanya dari tabel dan mereka mulai menulis "pilih semuanya dari ..." tepat di editor query SQL. Dia memiliki reaksi yang sama dengan yang Anda lakukan.
Ellesedil
22

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

Random Integer : untuk mendapatkan integer acak antara mindan max, gunakan kode berikut

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

Random Floating Point Number : untuk mendapatkan nomor floating point acak antara mindan max, gunakan kode berikut

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

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

Razan Paul
sumber
14

Matematika bukanlah kelebihan saya, tetapi saya telah mengerjakan sebuah proyek di mana saya perlu menghasilkan banyak angka acak antara positif dan negatif.

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

Misalnya

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

Tentu saja, Anda juga dapat menambahkan beberapa validasi untuk memastikan Anda tidak melakukan ini dengan selain angka. Pastikan juga bahwa min selalu kurang dari atau sama dengan maks.

Petter Thowsen
sumber
5
Ini salah. min + Math.random() * maxakan memberi Anda angka antara min dan min + maks, yang bukan yang Anda inginkan. Cabang pertama dari ifbenar, tetapi bisa disederhanakan untuk mengatakan return min + Math.random() * (max - min), yang merupakan solusi yang benar terlepas dari apakah min positif atau negatif (lihat jawaban lain). Juga, perlu diingat bahwa Anda masih perlu menurunkan hasilnya jika Anda tidak ingin pecahan.
Avish
10

Saya menulis fungsi yang lebih fleksibel yang dapat memberi Anda nomor acak tetapi tidak hanya bilangan bulat.

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

Versi tetap.

ElChupacabra
sumber
Ini bukan solusi yang baik karena tidak akan bekerja dengan nol sebagai nilai minimal. Lihat jawaban @ Lior.
Sebastien
Tentu saja ia bekerja dengan nol sebagai nilai minimum. Apakah kamu sudah mencoba? Tidak ada alasan mengapa itu tidak berhasil. Ini tidak akan berfungsi dengan 0 sebagai interval yang tidak aneh (interval = 0? ...).
ElChupacabra
Saya menjalankan beberapa kali fungsi ini dengan nol sebagai nilai min dan tidak pernah mendapatkan nol dalam output. Atau saya tidak cukup beruntung ...
Sebastien
Kamu benar. "+ interval" berada di tempat yang salah. Tolong, coba sekarang. Hal aneh yang terkadang console.log memberi saya 0,300000004 bukannya 0,3 seperti 3 * 0,1 tidak akan persis 0,3.
ElChupacabra
9

Contoh

Kembalikan angka acak antara 1 dan 10:

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

Hasilnya bisa: 3

Coba sendiri: di sini

-

atau menggunakan lodash / undescore:

_.random(min, max)

Docs: - lodash - undescore

Sebastián Lara
sumber
1
jadi kamu butuh 9 atau 10 kan? Jika ya: const randomNumber = Math.floor ((Math.random () * 10) + 1) const nineOrTen = randomNumber% 2 === 0? 9: 10
Sebastián Lara
7

Terlepas dari banyak jawaban dan hasil yang hampir sama. Saya ingin menambahkan jawaban saya dan menjelaskan cara kerjanya. Karena itu penting untuk memahami kerjanya daripada menyalin menyisipkan satu kode baris. Menghasilkan angka acak hanyalah matematika sederhana.

KODE:

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
sumber
6

Saya sedang mencari generator nomor acak yang ditulis dalam TypeScript dan saya telah menulis ini setelah membaca semua jawaban, berharap ini akan bekerja untuk coders TypeScript.

    Rand(min: number, max: number): number {
        return (Math.random() * (max - min + 1) | 0) + min;
    }   
Erdi İzgi
sumber
5

Math.random() cepat dan cocok untuk banyak tujuan, tetapi tidak tepat jika Anda membutuhkan nilai-nilai yang aman secara kriptografis (tidak aman), atau jika Anda memerlukan bilangan bulat dari distribusi yang sama sekali tidak bias (pendekatan multiplikasi yang digunakan dalam jawaban lain menghasilkan nilai-nilai tertentu sedikit lebih sering lebih sering dari yang lain).

Dalam kasus seperti itu, kita dapat menggunakan crypto.getRandomValues()untuk menghasilkan integer aman, dan menolak nilai apa pun yang dihasilkan yang tidak dapat dipetakan secara seragam ke dalam rentang target. Ini akan lebih lambat, tetapi seharusnya tidak signifikan kecuali Anda menghasilkan nilai yang sangat besar.

Untuk memperjelas masalah distribusi bias, pertimbangkan kasus di mana kami ingin menghasilkan nilai antara 1 dan 5, tetapi kami memiliki generator angka acak yang menghasilkan nilai antara 1 dan 16 (nilai 4-bit). Kami ingin memiliki jumlah yang sama dari pemetaan nilai yang dihasilkan untuk setiap nilai output, tetapi 16 tidak dibagi rata dengan 5: ia meninggalkan sisa dari 1. Jadi kita perlu menolak 1 dari nilai yang mungkin dihasilkan, dan hanya melanjutkan ketika kita mendapatkan salah satu dari 15 nilai lebih rendah yang dapat dipetakan secara seragam ke dalam kisaran target kami. Perilaku kita bisa terlihat seperti kodesemu ini:

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.

Kode berikut menggunakan logika yang sama, tetapi menghasilkan bilangan bulat 32-bit sebagai gantinya, karena itulah ukuran bilangan bulat umum terbesar yang dapat diwakili oleh numbertipe standar JavaScript . (Ini dapat dimodifikasi untuk menggunakan BigInts jika Anda membutuhkan rentang yang lebih besar.) Terlepas dari rentang yang dipilih, fraksi dari nilai yang dihasilkan akan selalu kurang dari 0,5, sehingga jumlah penolakan yang diharapkan akan selalu kurang dari 1,0 dan biasanya mendekati 0,0; Anda tidak perlu khawatir tentang hal itu berulang selamanya.

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
sumber
Sekarang, ini adalah apa yang saya sebut berlebihan.
2xSamurai
2
@ 2xSamurai Di sana, saya memperbarui jawaban untuk menjelaskan mengapa Anda mungkin membutuhkan ini dan cara kerjanya. Apakah itu lebih baik? : P
Jeremy Banks
Sama sekali tidak berlebihan jika Anda ingin nomor acak yang aman secara kriptografis dan terdistribusi seragam. Menghasilkan angka acak yang memenuhi persyaratan itu sulit. Jawaban yang bagus, @JeremyBanks.
thomaskonrad
4

Menambahkan floatdengan versi presisi tetap berdasarkan intversi dalam jawaban @ Francisc:

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

begitu:

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

dan untuk jawaban int

randomFloatFromInterval(1,3,0) // => 1, 2, 3
yonatanmn
sumber
3

Nomor integer acak crypto-kuat dalam rentang [a, b] (asumsi: 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
sumber
1

Ini seharusnya bekerja:

const getRandomNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min
sbr_amd
sumber
1

Saya menemukan cara baru yang hebat untuk melakukan ini menggunakan parameter default ES6. Ini sangat bagus karena memungkinkan satu argumen atau dua argumen. Ini dia:

function random(n, b = 0) {
    return Math.random() * (b-n) + n;
}
maburdi94
sumber
1

Ini terlambat sekitar sembilan tahun, tetapi randojs.com menjadikan ini satu kalimat sederhana:

rando(1, 6)

Anda hanya perlu menambahkan ini ke kepala dokumen html Anda, dan Anda dapat melakukan apa saja yang Anda inginkan dengan mudah secara acak. Nilai acak dari array, elemen jquery acak, properti acak dari objek, dan bahkan mencegah pengulangan jika diperlukan.

<script src="https://randojs.com/1.0.0.js"></script>
Aaron Plocharczyk
sumber
Mengapa menambahkan ketergantungan untuk melakukan sesuatu yang sudah satu-liner? Obsesi untuk menambah perpustakaan di komunitas JS gila
Daniel Cooke
lebih mudah dibaca dan diingat. Saya setuju
Aaron Plocharczyk
1

Ini berfungsi untuk saya dan menghasilkan nilai-nilai seperti fungsi library standar random.randint Python :


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

console.log("Random integer: " + randint(-5, 5));
gnrfan
sumber
1

Coba gunakan:

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

AyushKatiyar
sumber
1

mengembalikan 1-6 seperti dadu pada dasarnya,

return Math.round(Math.random() * 5 + 1);
Husky931
sumber