Câu hỏi Tạo số nguyên ngẫu nhiên trong JavaScript trong một phạm vi cụ thể?


Làm cách nào tôi có thể tạo một số nguyên ngẫu nhiên giữa hai biến được chỉ định trong Javascript, ví dụ: x = 4 và y = 8 sẽ xuất ra bất kỳ 4, 5, 6, 7, 8?


1486
2017-10-06 20:05


gốc


đây là một ý chính hữu ích: gist.github.com/kerimdzhanov/7529623 - Dan K.K.
Lưu ý: đối với những người sử dụng npm và tìm kiếm giải pháp nhanh chóng, đáng tin cậy và sẵn sàng lodash.randomcó thể dễ dàng yêu cầu với một dấu chân siêu nhỏ (nó sẽ chỉ nhập chính phương thức đó chứ không phải toàn bộ lodash). - Nobita
nếu cần mật mã hóa developer.mozilla.org/en-US/docs/Web/API/RandomSource/… - happy


Các câu trả lời:


Có một số ví dụ về Mạng nhà phát triển Mozilla trang:

/**
 * 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)
 * Using Math.round() will give you a non-uniform distribution!
 */
function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

Đây là logic đằng sau nó. Đó là một quy tắc đơn giản gồm ba:

Math.random() trả về một Number giữa 0 (bao gồm) và 1 (độc quyền). Vì vậy, chúng tôi có một khoảng thời gian như thế này:

[0 .................................... 1)

Bây giờ, chúng tôi muốn một số giữa min (bao gồm) và max (độc quyền):

[0 .................................... 1)
[min .................................. max)

Chúng ta có thể sử dụng Math.random để có được phóng viên trong khoảng [min, max). Nhưng, trước tiên chúng ta nên tính toán một chút vấn đề bằng cách trừ đi min từ khoảng thứ hai:

[0 .................................... 1)
[min - min ............................ max - min)

Điều này cho:

[0 .................................... 1)
[0 .................................... max - min)

Bây giờ chúng ta có thể áp dụng Math.random và sau đó tính toán phóng viên. Hãy chọn một số ngẫu nhiên:

                Math.random()
                    |
[0 .................................... 1)
[0 .................................... max - min)
                    |
                    x (what we need)

Vì vậy, để tìm x, chúng tôi sẽ làm:

x = Math.random() * (max - min);

Đừng quên thêm min trở lại, để chúng tôi nhận được một số trong khoảng [min, max):

x = Math.random() * (max - min) + min;

Đó là chức năng đầu tiên của MDN. Cái thứ hai, trả về một số nguyên giữa min và max, bao gồm cả hai.

Bây giờ để lấy số nguyên, bạn có thể sử dụng round, ceil hoặc là floor.

Bạn đã có thể sử dụng Math.round(Math.random() * (max - min)) + mintuy nhiên, điều này cho phép phân phối không đồng đều. Cả hai, min và max chỉ có khoảng một nửa cơ hội để cuộn:

min...min+0.5...min+1...min+1.5   ...    max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘   ← Math.round()
   min          min+1                          max

Với max loại trừ khỏi khoảng thời gian, nó thậm chí còn có ít cơ hội để cuộn hơn min.

Với Math.floor(Math.random() * (max - min +1)) + min bạn có phân phối hoàn toàn đồng đều.

min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
|        |        |         |        |        |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘   ← Math.floor()
   min     min+1               max-1    max

Bạn không thể sử dụng ceil() và -1 trong phương trình đó bởi vì max bây giờ đã có một cơ hội ít hơn để cuộn, nhưng bạn có thể cuộn (không mong muốn) min-1 kết quả quá.


3055
2017-10-06 20:08



Nó chỉ làm điều đó bởi vì nó đang gọi floor, làm tròn xuống. - Josh Stodola
@ thezachperson31 Bạn có thể sử dụng round, nhưng sau đó cả hai, min và max chỉ có một nửa cơ hội để cuộn như những con số khác. Bạn cũng có thể trừ một và lấy ceil. Tuy nhiên, điều này max số lượng ít cơ hội hơn để cuộn do [0,1) Khoảng thời gian. - Christoph
Tôi đã tạo một JSFiddle nếu có ai muốn kiểm tra sự phân bố của phương thức này: jsfiddle.net/F9UTG/1 - ahren
@ JackFrost yeah, đúng thế. Bạn không câm, bạn chỉ học :) - Ionuț G. Stan
Câu hỏi này là cũ, nhưng sự hiểu biết câu trả lời này đã cho tôi cách quá nhiều thời gian O.o, tôi nghĩ rằng mở rộng math.random trên phiên bản JavaScript tiếp theo sẽ là loại hữu ích - Jonathan Ortega


var randomnumber = Math.floor(Math.random() * (maximum - minimum + 1)) + minimum;

463
2017-10-06 20:09



Tôi biết đây là câu trả lời rất cũ, nhưng sử dụng (Math.random() * (maximum - minimum + 1) ) << 0 nhanh hơn. - Ismael Miguel
@IsmaelMiguel Sử dụng toán tử nhị phân (x << 0, x | 0, ~~x) thay vì Math.floor() chuyển đổi x thành một hai bổ sung với phạm vi nhỏ hơn nhiều so với Number.MAX_SAFE_INTEGER (2³²⁻¹ so với 2⁵³), do đó bạn phải thận trọng sử dụng nó! - le_m


Math.random ()

Từ Mozilla Tài liệu mạng nhà phát triển:

// Returns a random integer between min (include) and max (include)

Math.floor(Math.random() * (max - min + 1)) + min;

Các ví dụ hữu ích:

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

72
2018-03-25 01:58





function getRandomizer(bottom, top) {
    return function() {
        return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
    }
}

sử dụng:

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.
}

phá vỡ:

Chúng ta đang trả về một hàm (mượn từ lập trình hàm) khi được gọi, sẽ trả về một số nguyên ngẫu nhiên giữa các giá trị bottom và top, bao gồm. Chúng tôi nói 'bao gồm' bởi vì chúng tôi muốn bao gồm cả dưới cùng và trên cùng trong phạm vi số có thể được trả lại. Cách này, getRandomizer( 1, 6 ) sẽ trả về 1, 2, 3, 4, 5 hoặc 6.

(dưới cùng là số thấp hơn, trên cùng là số lớn hơn)

Math.random() * ( 1 + top - bottom )

Math.random() trả về một ngẫu nhiên gấp đôi từ 0 đến 1, và nếu chúng ta nhân nó bằng một cộng với sự khác biệt giữa top và bottom, chúng ta sẽ tăng gấp đôi ở đâu đó giữa 0 và 1+b-a.

Math.floor( Math.random() * ( 1 + top - bottom ) )

Math.floor làm tròn số xuống số nguyên gần nhất. Bây giờ chúng ta có tất cả các số nguyên giữa 0 và top-bottom. The 1 trông khó hiểu, nhưng nó cần phải có bởi vì chúng tôi luôn làm tròn xuống, do đó, số đầu sẽ không bao giờ thực sự đạt được mà không có nó. Số thập phân ngẫu nhiên mà chúng tôi tạo ra cần phải nằm trong phạm vi 0 đến (1+top-bottom) vì vậy chúng tôi có thể làm tròn và nhận được một int trong phạm vi 0 đến top-bottom

Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom

Mã trong ví dụ trước đã cho chúng ta một số nguyên trong phạm vi 0 và top-bottom, vì vậy tất cả những gì chúng ta cần làm bây giờ là thêm bottom với kết quả đó để có được một số nguyên trong phạm vi bottom và top bao gồm. : D


LƯU Ý: Nếu bạn vượt qua trong một giá trị không nguyên hoặc số lớn hơn đầu tiên bạn sẽ nhận được hành vi không mong muốn, nhưng trừ khi bất cứ ai yêu cầu nó tôi sẽ không đi sâu vào mã kiểm tra đối số vì nó khá xa ý định của câu hỏi gốc .


48
2017-10-06 20:08



Tôi nhận ra điều này là khoảng 2½ năm sau, nhưng với đầu vào 1 và 6, hàm của bạn trả về các giá trị 1,2,3,4 và 5, nhưng không bao giờ là 6, vì nó sẽ là "bao gồm". - some
@some, Có thể tệ hơn, tôi 2½ năm + 1 ngày sau ^^ - ajax333221
1, tôi đã kiểm tra mã của bạn, nó dường như tạo ra một giá trị chính xác. Cấu trúc sáng tạo để xử lý các kịch bản cố định có thể được lặp lại rất nhiều trong mã. - Chris
Tại sao bạn có một hàm trong một hàm cho điều này? - Alph.Dev
@ Alph.Dev Để phân tách logic sử dụng trình tạo số ngẫu nhiên từ logic quyết định chính xác phân phối số ngẫu nhiên nào cần sử dụng. Khi mã sử dụng trình tạo số ngẫu nhiên chấp nhận nó như một tham số (một hàm 0 đối số luôn trả về một số ngẫu nhiên mới), nó có thể làm việc với bất kỳ loại trình tạo số ngẫu nhiên nào. - Gordon Gustafson


Trả lại một số ngẫu nhiên từ 1 đến 10:

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

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

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

27
2018-03-28 11:31



của bạn là "giữa" bao gồm hay độc quyền? tức là [1,10], [1,10), (1,10] hoặc (1,10)? - evandrix
Nó bao gồm một phần: [1, *) - Ivan Z
nhu cầu của + 1 ở phần cuối của hàm là gì? Nó hoạt động hoàn hảo tôi đoán. - Shachi


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

Thay thế nếu bạn đang sử dụng Underscore.js bạn có thể dùng

_.random(min, max)

26
2018-02-09 19:51



Lodash cung cấp này là tốt. - Walter Roman
Dấu gạch dưới thực sự cung cấp _.uniqueId() chức năng bạn có thể gọi cho các mô hình phía máy khách. - obfk
Sử dụng toán tử nhị phân (x << 0, x | 0, ~~x) thay vì Math.floor() chuyển đổi x thành một hai bổ sung với phạm vi nhỏ hơn nhiều so với Number.MAX_SAFE_INTEGER (2³²⁻¹ so với 2⁵³), do đó bạn phải thận trọng sử dụng nó! - le_m


Các câu trả lời khác không tính đến các thông số hoàn toàn hợp lý của 0 và 1. Thay vào đó bạn nên sử dụng round  thay thế của ceil hoặc là 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

12
2017-07-21 16:42



Câu trả lời của bạn là đúng nhưng tôi nghĩ rằng ví dụ của bạn là sai .. console.log(randomNumber(5,6)); # 9 6 6 5 7 7 9 & 7 có từ 5 đến 6 không? ...... bạn nên sửa nó hoặc giải thích .. - Sachin


Sau khi tạo ra một số ngẫu nhiên bằng cách sử dụng một chương trình máy tính, nó vẫn được coi là một số ngẫu nhiên nếu số được chọn là một phần hoặc số đầy đủ của số đầu tiên. Nhưng nếu nó đã được thay đổi, thì các nhà toán học không chấp nhận nó như một con số ngẫu nhiên và họ có thể gọi nó là một con số thiên vị. Nhưng nếu bạn đang phát triển một chương trình cho một nhiệm vụ đơn giản, đây sẽ không phải là một trường hợp cần xem xét. Nhưng nếu bạn đang phát triển một chương trình để tạo một số ngẫu nhiên cho một thứ có giá trị như chương trình xổ số, hoặc trò chơi cờ bạc, thì chương trình của bạn sẽ bị quản lý từ chối nếu bạn không cân nhắc về trường hợp trên.

Vì vậy, đối với những loại người đó, đây là gợi ý của tôi:

Tạo một số ngẫu nhiên bằng cách sử dụng Math.random().(nói cái này 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.

Nếu bạn biết cách đọc bảng số ngẫu nhiên để chọn một số ngẫu nhiên, bạn biết quá trình trên (nhân với 1, 10, 100, v.v.) không vi phạm cái mà tôi đã đề cập ở đầu (vì nó chỉ thay đổi vị trí của dấu thập phân.)

Nghiên cứu ví dụ sau và phát triển nó theo nhu cầu của bạn.

Nếu bạn cần một mẫu [0,9] thì tầng n * 10 là câu trả lời của bạn và nếu cần [0,99] thì tầng n * 100 là câu trả lời của bạn và vân vân.

Bây giờ hãy tham gia vào vai trò của bạn:

Bạn đã hỏi số trong phạm vi cụ thể. - Bằng cách lấy một số từ [1,6] bằng cách cuộn một cái chết, sau đó bạn thiên vị thành [1,6] nhưng vẫn là ngẫu nhiên nếu và chỉ khi chết là không thiên vị .)

Vì vậy, hãy xem xét phạm vi của bạn ==> [78, 247] số phần tử trong phạm vi = 247 - 78 + 1 = 170; (vì cả hai ranh giới đều được bao gồm.

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

Lưu ý: Trong phương thức một, đầu tiên tôi tạo một mảng chứa các số mà bạn cần và sau đó đặt chúng một cách ngẫu nhiên vào một mảng khác. Trong phương pháp hai, tạo số ngẫu nhiên và kiểm tra những số nằm trong phạm vi mà bạn cần. Sau đó đặt nó vào một mảng. Ở đây tôi tạo ra hai số ngẫu nhiên và sử dụng tổng số chúng để tối đa hóa tốc độ của chương trình bằng cách giảm thiểu tỷ lệ thất bại có được một số hữu ích. Tuy nhiên, việc thêm số được tạo ra cũng sẽ tạo ra một số sinh khí. Vì vậy, tôi sẽ giới thiệu phương pháp đầu tiên của tôi để tạo ra các số ngẫu nhiên trong một phạm vi cụ thể.

Trong cả hai phương pháp, bảng điều khiển của bạn sẽ hiển thị kết quả. (Nhấn f12 trong Chrome để mở bảng điều khiển)


9
2018-02-10 13:22



"ngẫu nhiên" không nhất thiết có nghĩa là "phân phối đồng đều". "thiên vị" không ngụ ý "không ngẫu nhiên". ngẫu nhiên có nghĩa là rút ra từ một phân bố xác suất. - syzygy
Hầu như không thể nói câu trả lời này đang cố gắng nói gì. Tuy nhiên, nếu bạn cần số ngẫu nhiên để sử dụng như số xổ số và cờ bạc. Trước tiên, có lẽ bạn không nên tạo chúng trên máy khách. Thứ hai, bạn cần một bộ tạo số ngẫu nhiên an toàn mã hóa và bản ngã được cung cấp là không đủ. Gọi ngẫu nhiên nhiều lần không làm cho kết quả "ngẫu nhiên hơn". Tác giả dường như quan tâm về thiên vị, nhưng không cung cấp một bản ngã tốt để ngăn chặn nó. Trong thực tế, các câu trả lời ngắn khác cung cấp các số ngẫu nhiên tạo ra các số ngẫu nhiên (giả sử máy phát ngẫu nhiên cơ bản là không thiên vị). - Jeff Walker Code Ranger
Tôi đã thử nó nhưng chỉ số không ok (giải pháp 1). - loretoparisi
@ JeffWalkerCodeRanger Tôi nghĩ ý của anh ấy là với thuật toán "bình thường" [tức là Math.floor(Math.random() * (6 - 1 + 1) + 1)] các số 1 và 6 sẽ nhất thiết phải được cuộn ít hơn 2, 3, 4 và 5. Tuy nhiên, sự khác biệt về cơ bản là không đáng kể. - Anthony


Đối với một số nguyên ngẫu nhiên với một phạm vi, hãy thử:

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

8
2017-10-25 22:15





Đây là lớp thực thi ngẫu nhiên MS DotNet trong 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;
}());

Sử dụng:

        var r = new Random();
        var nextInt = r.Next(1, 100); //returns an integer between range
        var nextDbl = r.NextDouble(); //returns a random decimal

8
2017-11-15 05:38