Tạo số ngẫu nhiên giữa hai số trong JavaScript


1798

Có cách nào để tạo một số ngẫu nhiên trong một phạm vi được chỉ định (ví dụ: từ 1 đến 6: 1, 2, 3, 4, 5 hoặc 6) trong JavaScript không?


12
Math.floor (Math.random () * 7)
Amjad Masad

65
Chắc chắn .. Math.floor (Math.random () * 6 + 1)
Amjad Masad

3
Nabil Kadimi đã viết một bài viết về cách tạo ra các số ngẫu nhiên âm quá.
madc

đây là một ý chính hữu ích: gist.github.com/kerimdzhanov/7529623
Dan KK

tại sao một giải pháp như thế này Math.floor((Math.random()*10)+1);không thể làm việc cho bạn như được chỉ định ở đây tại w3schools.com/jsref/jsref_random.asp ..?
shashwat

Câu trả lời:


2117

Quan trọng

Các mã sau chỉ hoạt động nếu giá trị tối thiểu là 1. Nó không hoạt động cho các giá trị tối thiểu khác hơn1 .

Nếu bạn muốn lấy số nguyên ngẫu nhiên trong khoảng từ 1 ( và chỉ 1 ) đến 6, bạn sẽ tính:

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

Ở đâu:

  • 1 là số bắt đầu
  • 6 là số kết quả có thể có (1 + bắt đầu (6) - kết thúc (1) )

45
Trong khi điều này sẽ hoạt động, @Mike, tốt nhất là chỉ ra phiên bản chung chung hơn như Francisc có dưới đây :-).
Raymond Machira

59
-1. Sau khi Googling tôi tìm thấy câu hỏi này, tiêu đề là "" Tạo giá trị ngẫu nhiên giữa hai số trong Javascript "." Sẽ không hoạt động nếu giá trị tối thiểu là 0
Ydhem

18
Không hoạt động nếu bạn muốn một số giữa hai số lớn hơn, vd. Math.floor (Math.random () * 900) + 700
Cướp

15
Điều đó chỉ hoạt động nếu mức tối thiểu là 1. Nếu min là 2 và chúng tôi vẫn sử dụng Math.floor(Math.random() * 6) + 2có nghĩa là nếu Math.random()kết quả thành 0,99 thì giá trị ngẫu nhiên của chúng tôi sẽ là7
chống độc

28
Mã này không tốt bởi vì, không hoạt động với bất kỳ số nào. Mã @Francisc là chính xác.
Vua sư tử

2286
function randomIntFromInterval(min, max) { // min and max included 
  return Math.floor(Math.random() * (max - min + 1) + min);
}

Những gì nó làm "thêm" là nó cho phép các khoảng ngẫu nhiên không bắt đầu bằng 1. Vì vậy, bạn có thể nhận được một số ngẫu nhiên từ 10 đến 15 chẳng hạn. Uyển chuyển.


5
điều này cũng tuyệt vời bởi vì nếu ai đó không bao gồm toarg, thì fromarg tăng gấp đôi tối đa
Jason

12
Xin chào. Đây là từ 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/ mẹo )
Francisc

5
Đọc bình luận trên. Ngẫu nhiên là bên trong [0,1), không phải [0,1].
Francisc

3
Hoạt động tuyệt vời nếu số thấp hơn là 0.
Robin Zimmermann

2
Lưu ý rằng giải pháp này chỉ đúng nếu tối thiểu và tối đa là số nguyên, nếu không bạn có thể nhận được kết quả trong khoảng [min, ceil (max)]. Tức là bạn có thể nhận được một kết quả nằm ngoài phạm vi vì cao hơn tối đa.
collimarco

328

Toán.random ()

Trả về một số ngẫu nhiên số nguyên giữa min ( bao gồm ) và max ( bao gồm ):

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

Hoặc bất kỳ số ngẫu nhiên nào giữa min ( bao gồm ) và max ( không bao gồm ):

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

Ví dụ hữu ích (số nguyên):

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

** Và luôn luôn tốt đẹp để được nhắc nhở (Mozilla):

Math.random () không cung cấp số ngẫu nhiên an toàn bằng mật mã. Không sử dụng chúng cho bất cứ điều gì liên quan đến an ninh. Thay vào đó, hãy sử dụng API Web Crypto và chính xác hơn là phương thức window.crypto.getRandomValues ​​().


Một cái gì đó làm tôi bối rối ... Math.floor (..) đảm bảo rằng số đó là một số nguyên trong đó Math.round (..) sẽ phân phối không đồng đều. Tham chiếu: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
mẹo

1
Tôi tin tưởng câu trả lời này. Bất cứ ai có thể đưa ra một liên kết hoặc giải thích rõ ràng về lý do tại sao điều này làm việc? Có lẽ một ví dụ về cách Math.round sẽ đưa ra một sự thiên vị, và tại sao điều đó có nghĩa là chúng ta phải sử dụng công thức có vẻ khá phức tạp này?
Robin Andrew

6
@alikuli Đối với một loạt các [1,2], có 25% cơ hội Math.random()sẽ cung cấp cho bạn một số từ một trong những [0,0.49], [0.5,0.99], [1,1.49], [1.5,1.99]. Làm tròn các khoảng đó sẽ dẫn đến 0, 1, 1, 2 không phải là phân phối chẵn. Kết quả sàn của họ trong 0, 0, 1, 1.
pishpish

1
@shuji Đây , trong số những người khác, câu trả lời chính xác. Tôi chỉ muốn làm rõ tại sao sử dụng Math.roundhơn Math.floorsẽ cho kết quả khác nhau.
pishpish

Giải pháp chính xác nhất tôi đã tìm thấy: function getRandomInt(min, max) { return Math.round((min - 0.5) + Math.random() * (max - min + 1)); }
Sadik

91

Các giải pháp khác:

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

Thử trực tuyến


6
bạn có phiền giải thích (hoặc đưa ra tài liệu tham khảo cho) ~ sintaxis không? Tôi chưa từng thấy nó trước đây! Giải pháp tao nhã nhưng khó hiểu.
DiegoDĐ

27
Double Tilde ~~aBitwise OR (a | 0) là những cách nhanh hơn để viết Math.floor (a)
edi9999

7
a | 0cũng là cách nhanh nhất và tối ưu nhất để chuyển đổi một chuỗi thành một số nguyên. Nó chỉ hoạt động với các chuỗi chứa số nguyên ( "444""-444"), tức là không có số float / phân số. Nó mang lại một 0cho tất cả mọi thứ thất bại. Đây là một trong những tối ưu hóa chính đằng sau asm.js.
pilau

3
Lưu ý: nếu bạn đang làm việc với một số lượng lớn thực sự thì dấu ngã kép sẽ không hoạt động. Hãy thử ~~(Math.random() * (50000000000000 - 0 + 1)) + 0Math.floor(Math.random() * (50000000000000 - 0 + 1)) + 0
BrunoLM

3
"Dấu ngã kép và bitwise OR / là những cách nhanh hơn để viết Math dot floor" là một khớp nối có vần điệu đẹp làm bừng sáng buổi sáng của tôi. Cảm ơn @ edi9999!
teedyay

60

TL; DR

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

Để có được số ngẫu nhiên generateRandomInteger(-20, 20);

KHAI THÁC DƯỚI ĐÂY

Chúng ta cần lấy một số nguyên ngẫu nhiên, giả sử X giữa min và max.

Đúng?

tức là tối thiểu <= X <= max

Nếu chúng ta trừ đi tối thiểu khỏi phương trình, điều này tương đương với

0 <= (X - phút) <= (tối đa - phút)

Bây giờ, cho phép nhân này với một số ngẫu nhiên r

0 <= (X - phút) * r <= (tối đa - phút) * r

Bây giờ, hãy thêm trở lại min vào phương trình

phút <= min + (X - phút) * r <= min + (tối đa - phút) * r

Bây giờ, hãy chọn một hàm dẫn đến r sao cho nó thỏa mãn phạm vi phương trình của chúng tôi là [min, max]. Điều này chỉ có thể nếu 0 <= r <= 1

ĐỒNG Ý. Bây giờ, phạm vi của r tức là [0,1] rất giống với kết quả của hàm Math.random (). Phải không?

Hàm Math.random () trả về số dấu phẩy động, giả ngẫu nhiên trong phạm vi [0, 1); nghĩa là, từ 0 (bao gồm) cho đến nhưng không bao gồm 1 (độc quyền)

Ví dụ,

Trường hợp r = 0

min+ 0 * ( max- min) = phút

Trường hợp r = 1

min+ 1 * ( max- min) = tối đa

Trường hợp ngẫu nhiên sử dụng Math.random 0 <= r <1

min+ r * ( max- min) = X , trong đó X có phạm vi tối thiểu <= X < max

Kết quả X ở trên là một số ngẫu nhiên. Tuy nhiên do Math.random () giới hạn bên trái của chúng tôi được bao gồm và giới hạn bên phải là độc quyền. Để bao gồm quyền ràng buộc của chúng tôi, chúng tôi tăng quyền bị ràng buộc bởi 1 và kết quả sàn.

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

Để có được số ngẫu nhiên

generateRandomInteger(-20, 20);



24
var x = 6; // can be any number
var rand = Math.floor(Math.random()*x) + 1;

2
Thật. Tôi quên rand là 0. Đã sửa nó.
ryebr3ad

3
Đó là một phần Pseudocode ... ai đó có thể nghĩ nó là thật và cố gắng sử dụng nó như thế.
trọng lực

35
@gravityboy Bạn đang nói về cái gì vậy? Nếu ai đó không thể thay thế một số cho [chọn một số ...], họ có thể không phù hợp làm lập trình viên.
ryebr3ad

7
@ ryebr3ad -1! nó nói trong javascript không phải bằng mã giả và cũng không phải tất cả các độc giả đều là những lập trình viên hoàn thành. Nhiều người mới bắt đầu!
Steve

3
@ ryebr3ad: Tôi đã có một đồng nghiệp đang dạy thực tập về môi trường cơ sở dữ liệu mà họ sẽ cần hỗ trợ. Anh ta bảo họ chọn mọi thứ trong một bảng và họ bắt đầu viết "chọn mọi thứ trong ..." ngay trong trình soạn thảo truy vấn SQL. Anh ấy có phản ứng giống như bạn đã làm.
Ellesedil

22

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

Số nguyên ngẫu nhiên : để lấy số nguyên ngẫu nhiên giữa minmax, sử dụng mã sau

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

Số dấu phẩy động ngẫu nhiên: để có được một số dấu phẩy động ngẫu nhiên giữa minmax, sử dụng mã sau đây

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

Tham khảo: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random


14

Toán học không phải là điểm mạnh của tôi, nhưng tôi đã làm việc trong một dự án mà tôi cần tạo ra rất nhiều số ngẫu nhiên giữa cả tích cực và tiêu cực.

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

Ví dụ

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

Tất nhiên, bạn cũng có thể thêm một số xác nhận để đảm bảo bạn không làm điều này với bất kỳ thứ gì ngoài số. Cũng đảm bảo rằng min luôn nhỏ hơn hoặc bằng max.


5
Điều này chỉ đơn giản là sai. min + Math.random() * maxsẽ cung cấp cho bạn các số giữa min và min + max, đây không phải là điều bạn muốn. Nhánh đầu tiên iflà chính xác, nhưng có thể được đơn giản hóa để nói return min + Math.random() * (max - min), đó là giải pháp chính xác bất kể min là dương hay âm (xem các câu trả lời khác). Ngoài ra, hãy nhớ rằng bạn vẫn cần đưa ra kết quả nếu bạn không muốn phân số.
Avish

10

Tôi đã viết hàm linh hoạt hơn có thể cung cấp cho bạn số ngẫu nhiên nhưng không chỉ số nguyên.

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

Đã sửa phiên bản.


Đây không phải là một giải pháp tốt vì nó sẽ không hoạt động với giá trị tối thiểu bằng 0. Xem câu trả lời của @ Lior.
Sebastien

Tất nhiên nó hoạt động với giá trị 0 là min. Bạn đã thử chưa? Không có lý do tại sao nó có thể không hoạt động. Nó sẽ không hoạt động với 0 là khoảng không lạ (khoảng = 0? ...).
ElChupacabra

Tôi đã chạy nhiều lần hàm này với giá trị 0 là giá trị tối thiểu và không bao giờ thu được số 0 trong đầu ra. Hoặc tôi không đủ may mắn ...
Sebastien

Bạn đúng rồi. "+ khoảng" đã ở sai vị trí. Kiểm tra nó ngay bây giờ. Điều kỳ lạ mà đôi khi console.log mang lại cho tôi 0.300000004 thay vì 0.3 như 3 * 0.1 sẽ không chính xác là 0,3.
ElChupacabra

9

Thí dụ

Trả về một số ngẫu nhiên trong khoảng từ 1 đến 10:

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

Kết quả có thể là: 3

Hãy tự thử: tại đây

-

hoặc sử dụng lodash / undescore:

_.random(min, max)

Tài liệu: - lodash - undescore


1
vậy bạn cần 9 hay 10 đúng không? Nếu có: const RandomNumber = Math.floor ((Math.random () * 10) + 1) const ninOrTen = RandomNumber% 2 === 0? 9: 10
Sebastián Lara

7

Inspite của nhiều câu trả lời và kết quả gần như giống nhau. Tôi muốn thêm câu trả lời của tôi và giải thích nó hoạt động. Bởi vì điều quan trọng là phải hiểu hoạt động của nó hơn là sao chép dán một mã dòng. Tạo số ngẫu nhiên không có gì ngoài những phép toán đơn giản.

MÃ:

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));
}

6

Tôi đã tìm kiếm trình tạo số ngẫu nhiên được viết bằng TypeScript và tôi đã viết nó sau khi đọc tất cả các câu trả lời, hy vọng nó sẽ hoạt động cho các lập trình viên TypeScript.

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

5

Math.random() nhanh và phù hợp cho nhiều mục đích, nhưng không phù hợp nếu bạn cần các giá trị bảo mật bằng mật mã (không an toàn) hoặc nếu bạn cần số nguyên từ phân phối không thiên vị hoàn toàn thống nhất (phương pháp nhân được sử dụng trong các câu trả lời khác tạo ra một số giá trị nhất định thường xuyên hơn hơn những người khác).

Trong những trường hợp như vậy, chúng ta có thể sử dụng crypto.getRandomValues() để tạo các số nguyên an toàn và từ chối mọi giá trị được tạo mà chúng tôi không thể ánh xạ đồng nhất vào phạm vi mục tiêu. Điều này sẽ chậm hơn, nhưng nó không đáng kể trừ khi bạn tạo ra số lượng giá trị cực lớn.

Để làm rõ mối quan tâm phân phối thiên vị, hãy xem xét trường hợp chúng tôi muốn tạo giá trị từ 1 đến 5, nhưng chúng tôi có một trình tạo số ngẫu nhiên tạo ra các giá trị từ 1 đến 16 (giá trị 4 bit). Chúng tôi muốn có cùng số lượng ánh xạ giá trị được tạo cho mỗi giá trị đầu ra, nhưng 16 không chia đều cho 5: nó để lại phần còn lại là 1. Vì vậy, chúng tôi cần từ chối 1 trong các giá trị được tạo có thể và chỉ tiếp tục khi chúng tôi nhận được một trong 15 giá trị nhỏ hơn có thể được ánh xạ đồng nhất vào phạm vi mục tiêu của chúng tôi. Hành vi của chúng tôi có thể trông giống như mã giả này:

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.

Đoạn mã sau sử dụng logic tương tự, nhưng thay vào đó tạo ra số nguyên 32 bit, vì đó là kích thước số nguyên phổ biến lớn nhất có thể được biểu thị bằng numberloại tiêu chuẩn của JavaScript . (Điều này có thể được sửa đổi để sử dụng BigInts nếu bạn cần phạm vi lớn hơn.) Bất kể phạm vi đã chọn, phần giá trị được tạo bị từ chối sẽ luôn nhỏ hơn 0,5, vì vậy số lần từ chối dự kiến ​​sẽ luôn nhỏ hơn 1.0 và thường gần bằng 0,0; bạn không cần phải lo lắng về việc lặp đi lặp lại mãi mãi.

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]


Bây giờ, đây là những gì tôi gọi là quá mức cần thiết.
2xSamurai

2
@ 2xSamurai Ở đó, tôi đã cập nhật câu trả lời để giải thích lý do tại sao bạn có thể cần cái này và cách nó hoạt động. Điều đó có tốt hơn không? : P
Jeremy Banks

Hoàn toàn không phải là quá mức nếu bạn muốn các số ngẫu nhiên được phân phối đồng đều và an toàn về mặt mật mã. Tạo số ngẫu nhiên đáp ứng các yêu cầu đó là khó. Câu trả lời tuyệt vời, @JeremyBanks.
thomaskonrad

4

Thêm floatbằng phiên bản chính xác cố định dựa trên intphiên bản trong câu trả lời của @ Francisc:

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

vì thế:

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

và cho câu trả lời int

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

3

Số nguyên ngẫu nhiên mạnh về tiền điện tử trong phạm vi [a, b] (giả định: a <b)

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

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


1

Điều này sẽ làm việc:

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

1

Tôi phát hiện ra một cách mới tuyệt vời để làm điều này bằng cách sử dụng các tham số mặc định ES6. Nó rất tiện lợi vì nó cho phép một đối số hoặc hai đối số. Đây là:

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

1

Đây là khoảng chín năm muộn, nhưng randojs.com làm cho điều này một đơn giản:

rando(1, 6)

Bạn chỉ cần thêm phần này vào phần đầu của tài liệu html và bạn có thể thực hiện khá nhiều thứ bạn muốn một cách dễ dàng. Giá trị ngẫu nhiên từ mảng, yếu tố jquery ngẫu nhiên, thuộc tính ngẫu nhiên từ các đối tượng và thậm chí ngăn chặn sự lặp lại nếu cần.

<script src="https://randojs.com/1.0.0.js"></script>

Tại sao thêm một phụ thuộc để làm một cái gì đó đã là một lót? Nỗi ám ảnh về việc thêm thư viện trong cộng đồng JS là điên rồ
Daniel Cooke

dễ đọc và dễ nhớ hơn tôi đồng ý mặc dù
Aaron Plocharchot

1

Điều này làm việc cho tôi và tạo ra các giá trị như hàm thư viện tiêu chuẩn Random.randint của Python :


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

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

1

Hãy thử sử dụng:

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


1

về cơ bản để trở về 1-6 như một con xúc xắc,

return Math.round(Math.random() * 5 + 1);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.