Lấy một số ngẫu nhiên tập trung vào trung tâm


238

Có thể lấy số ngẫu nhiên trong khoảng 1-100 và giữ kết quả chủ yếu trong phạm vi 40-60 không? Ý tôi là, nó sẽ hiếm khi vượt ra khỏi phạm vi đó, nhưng tôi muốn nó chủ yếu nằm trong phạm vi đó ... Có khả thi với JavaScript / jQuery không?

Ngay bây giờ tôi chỉ đang sử dụng cơ bản Math.random() * 100 + 1.





20
Tôi thích câu hỏi này sẽ đi đến đâu, nhưng tôi nghĩ nó nên cụ thể hơn. Bạn có muốn phân phối Z (đường cong hình chuông), phân phối tam giác hoặc phân phối răng cưa nào đó không? Theo tôi, có nhiều khả năng để trả lời câu hỏi này.
Patrick Roberts

12
Điều này có thể được thực hiện trong javascript nhưng chắc chắn không có gì để làm với jQuery ... :)
A. Wolff

Câu trả lời:


397

Cách đơn giản nhất là tạo hai số ngẫu nhiên từ 0-50 và cộng chúng lại với nhau.

Điều này mang lại sự phân phối thiên về 50, theo cùng một cách lăn hai xu hướng xúc xắc về phía 7.

Trên thực tế, bằng cách sử dụng số lượng "xúc xắc" lớn hơn (như @Falco gợi ý) , bạn có thể thực hiện xấp xỉ gần hơn với đường cong hình chuông:

function weightedRandom(max, numDice) {
    var num = 0;
    for (var i = 0; i < numDice; i++) {
        num += Math.random() * (max/numDice);
    }    
    return num;
}

Số ngẫu nhiên có trọng số

JSFiddle: http://jsfiddle.net/797qhcza/1/


12
Đây là một giải pháp dễ dàng và nhanh chóng, có thể dễ dàng cân hơn, bằng cách thêm nhiều số hơn, ví dụ 4 x (0-25) và sẽ cung cấp cho bạn đường cong hình chuông đẹp cho phân phối!
Falco

8
Đây là một chút tuyệt vời của mã. Tôi nghĩ rằng tôi đang yêu nó. Đơn giản, nhanh chóng, hiệu quả; câu trả lời chính xác. Cảm ơn vì đã đăng tải điều này.
ctwheels

14
Câu trả lời tuyệt vời, nhưng trong trường hợp bất kỳ ai có ý định sử dụng điều này để tạo phân phối Bình thường, thì nó khá kém hiệu quả (và bạn cần phải chuyển đổi nó để có giá trị trung bình và độ lệch chuẩn mong muốn). Một tùy chọn hiệu quả hơn sẽ là biến đổi Box-Muller, khá dễ thực hiện và hiểu nếu bạn biết một chút về toán học.
Brendon

1
@RaziShaban Nó khá trực quan: Chỉ có một sự kết hợp của những cú ném chết có thêm tới 2 (chỉ là mắt rắn), nhưng có 6 kết hợp khác nhau cộng lại thành 7 (6-1, 5-2, 4-3, 3- 4, 2-5, 1-6). Nếu bạn khái quát hóa cho xúc xắc N-side, đỉnh luôn là N + 1.
Barmar

2
@RaziShaban Nghiên cứu về các biến ngẫu nhiên là một phần trung tâm của thống kê. Thực tế là khi chúng ta tăng xúc xắc, chúng ta tiếp cận một phân phối bình thường là Định lý giới hạn trung tâm nổi tiếng .
BlueRaja - Daniel Pflughoeft

48

Bạn có một số câu trả lời tốt ở đây đưa ra giải pháp cụ thể; Hãy để tôi mô tả cho bạn các giải pháp chung. Vấn đề là:

  • Tôi có một nguồn ít nhiều đồng đều số ngẫu nhiên phân phối giữa 0 và 1.
  • Tôi muốn tạo ra một chuỗi các số ngẫu nhiên theo một phân phối khác nhau.

Giải pháp chung cho vấn đề này là tìm ra hàm lượng tử của phân phối mong muốn của bạn, sau đó áp dụng hàm lượng tử cho đầu ra của nguồn thống nhất của bạn.

Hàm lượng tử là nghịch đảo của tích phân của hàm phân phối mong muốn của bạn . Hàm phân phối là hàm trong đó diện tích dưới một phần của đường cong bằng với xác suất mục được chọn ngẫu nhiên sẽ nằm trong phần đó.

Tôi đưa ra một ví dụ về cách làm như vậy ở đây:

http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/

Mã trong đó có trong C #, nhưng các nguyên tắc áp dụng cho bất kỳ ngôn ngữ nào; cần đơn giản để điều chỉnh giải pháp cho JavaScript.


2
Tôi thích cách tiếp cận này. Có thể muốn thêm rằng tồn tại một thư viện javascript tạo ra các bản phân phối Gaussian (và không bình thường khác): simjs.com/random.html
Floris

36

Lấy mảng số, vv không hiệu quả. Bạn nên lấy một ánh xạ lấy một số ngẫu nhiên từ 0 đến 100 và ánh xạ tới bản phân phối bạn cần. Vì vậy, trong trường hợp của bạn, bạn có thể thực hiện để có được một bản phân phối có nhiều giá trị nhất ở giữa phạm vi của bạn.f(x)=-(1/25)x2+4x

Phân phối


2
Chúng tôi không thực sự biết phân phối là cần thiết. "Chủ yếu là 40-60" ngụ ý đường cong hình chuông đối với tôi.
Lefty

vâng bạn đúng, có thể bạn cần một bản đồ tốt hơn, nhưng đó là chuyện nhỏ
iCaramba

3
Tôi sẽ tin bạn vì điều này không phải là lĩnh vực chuyên môn của tôi. Bạn có thể điều chỉnh chức năng và hiển thị đường cong mới?
Lefty

1
@Lefty - Đường cong chuông được đơn giản hóa trong xkhoảng từ 0 đến 100 (lấy từ câu hỏi này ):y = (Math.sin(2 * Math.PI * (x/100 - 1/4)) + 1) / 2
Sphinxxx

@Sphinxxx Đó không phải là đường cong hình chuông, đó là đường cong tội lỗi. Một đường cong hình chuông không bao giờ chạm vào trục x.
BlueRaja - Daniel Pflughoeft 17/07/18

17

Tôi có thể làm một cái gì đó như thiết lập một "cơ hội" cho số được phép "vượt ra khỏi giới hạn". Trong ví dụ này, 20% cơ hội con số sẽ là 1-100, nếu không, 40-60:

$(function () {
    $('button').click(function () {
        var outOfBoundsChance = .2;
        var num = 0;
        if (Math.random() <= outOfBoundsChance) {
            num = getRandomInt(1, 100);
        } else {
            num = getRandomInt(40, 60);
        }
        $('#out').text(num);
    });
    
    function getRandomInt(min, max) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<button>Generate</button>
<div id="out"></div>

câu đố: http://jsfiddle.net/kbv39s9w/


5
Có lẽ ai đó có nhiều chi tiết thống kê có thể sửa lỗi cho tôi và mặc dù điều này đạt được những gì OP đang tìm kiếm (vì vậy tôi đã bỏ phiếu), nhưng điều này sẽ không thực sự chọn một trong số 20% thời gian, đúng không? Trong giải pháp này, 20% thời gian bạn sẽ có cơ hội sau đó chọn # từ 1-100, bao gồm 40-60. Điều này thực sự sẽ không (0,2 * 0,8) 16% để chọn # ngoài giới hạn, hoặc tôi có thiếu điều gì không?
Josh

Không, bạn đúng. Đó chỉ là từ ngữ của tôi. Tôi sẽ sửa nó. Cảm ơn bạn!
Bitwise Creative

1
@Josh - Đó là điểm đẹp trên. Dưới đây là một bằng chứng đơn giản về những gì trông giống như jsfiddle.net/v51z8sd5 . Nó sẽ hiển thị phần trăm số được tìm thấy trong giới hạn và dao động khoảng 0,16 (16%).
Travis J

15

Tôi cần phải giải quyết vấn đề này vài năm trước và giải pháp của tôi dễ dàng hơn bất kỳ câu trả lời nào khác.

Tôi đã tạo ra 3 randoms giữa các giới hạn và tính trung bình cho chúng. Điều này kéo kết quả về phía trung tâm nhưng để nó hoàn toàn có thể đạt đến các chi.


7
Làm thế nào điều này tốt hơn / khác với câu trả lời của BlueRaja? Ở đó, anh ta lấy tổng số (2,3, ... bất kỳ số nào bạn muốn) và lấy số trung bình. Kết quả giống hệt với bạn khi bạn sử dụng một BellFactortrong số 3.
Floris

@floris tốt, tôi không viết mã trong họ ngôn ngữ nên câu trả lời thậm chí không có vẻ như nó đang làm điều tương tự như câu trả lời của tôi cho đến khi tôi đọc lại nó ngay bây giờ. Tôi đã tạo ra phương pháp của mình bằng một chút thử và sai và thấy rằng 3 randoms là số đúng. Ngoài ra, tôi có thể được thực hiện trong một dòng và vẫn dễ hiểu.
Lefty

2
Có thật không? Bạn không nghĩ rằng có bất kỳ sự tương đồng giữa JS và C? OK, tốt, hãy nói rằng tôi không thể nói EITHER của các ngôn ngữ đó, cũng như Java, mà đối với tôi, tất cả đều tương tự so với các ngôn ngữ mà tôi quen thuộc.
Lefty

1
Điểm công bằng, tôi thực sự bị thu hút chỉ bởi tiêu đề như là một điều gì đó tôi tự giải quyết và khá tự hào về cách tôi đã làm nó. Một lần nữa, tôi không biết đó là câu hỏi của js cho đến khi bạn nói điều đó. Thật may mắn, vì kỹ thuật của tôi không phụ thuộc vào ngôn ngữ và một số người dường như nghĩ rằng đó là một câu trả lời hữu ích.
Lefty

5
JavaScript thực sự một ngôn ngữ gia đình C ... nhưng ah tốt.
Joren

14

trông ngu ngốc nhưng bạn có thể sử dụng rand hai lần:

var choice = Math.random() * 3;
var result;

if (choice < 2){
    result = Math.random() * 20 + 40; //you have 2/3 chance to go there
}
else {
    result = Math.random() * 100 + 1;
}

11

Chắc chắn là có thể. Thực hiện ngẫu nhiên 1-100. Nếu số <30 thì tạo số trong phạm vi 1-100 nếu không tạo trong phạm vi 40-60.


11

Có rất nhiều cách khác nhau để tạo ra các số ngẫu nhiên như vậy. Một cách để làm điều đó là tính tổng của nhiều số ngẫu nhiên đồng nhất. Có bao nhiêu số ngẫu nhiên bạn tổng hợp và phạm vi của chúng sẽ xác định cách phân phối cuối cùng sẽ trông như thế nào.

Càng nhiều số bạn tổng hợp, nó sẽ càng thiên về trung tâm. Sử dụng tổng số 1 số ngẫu nhiên đã được đề xuất trong câu hỏi của bạn, nhưng như bạn nhận thấy không thiên về trung tâm của phạm vi. Các câu trả lời khác đã đề xuất sử dụng tổng của 2 số ngẫu nhiên hoặc tổng của 3 số ngẫu nhiên .

Bạn có thể nhận được nhiều thành kiến ​​hơn nữa đối với trung tâm của phạm vi bằng cách lấy tổng các số ngẫu nhiên hơn. Cuối cùng, bạn có thể lấy tổng số 99 số ngẫu nhiên, mỗi số là 0 hoặc 1. Đó sẽ là phân phối nhị thức. (Phân phối nhị thức theo một cách nào đó có thể được coi là phiên bản rời rạc của phân phối bình thường). Về lý thuyết, điều này vẫn có thể bao trùm toàn bộ phạm vi, nhưng nó có quá nhiều sự thiên vị đối với trung tâm mà bạn không bao giờ mong đợi để thấy nó đạt đến các điểm cuối.

Cách tiếp cận này có nghĩa là bạn có thể điều chỉnh mức độ thiên vị mà bạn muốn.


8

Điều gì về việc sử dụng một cái gì đó như thế này:

var loops = 10;
var tries = 10;
var div = $("#results").html(random());
function random() {
    var values = "";
    for(var i=0; i < loops; i++) {
        var numTries = tries;
        do {
            var num = Math.floor((Math.random() * 100) + 1);
            numTries--;
        }
        while((num < 40 || num >60) && numTries > 1)
        values += num + "<br/>";
    }
    return values;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="results"></div>

Cách tôi đã mã hóa nó cho phép bạn đặt một vài biến:
loops = số kết quả
lần thử = số lần hàm sẽ cố lấy một số trong khoảng 40-60 trước khi nó dừng chạy qua vòng lặp while

Đã thêm tiền thưởng: Nó sử dụng làm trong khi !!! Tuyệt vời nhất


8

Bạn có thể viết một hàm ánh xạ giá trị ngẫu nhiên giữa [0, 1)để [1, 100]theo trọng lượng. Xem xét ví dụ này:

0,0-1,0 đến 1-100 theo trọng lượng phần trăm

Ở đây, các 0.95bản đồ giá trị để giá trị giữa [61, 100].
Trong thực tế, chúng ta có .05 / .1 = 0.5, khi ánh xạ tới [61, 100], mang lại81 .

Đây là chức năng:

/*
 * Function that returns a function that maps random number to value according to map of probability
 */
function createDistributionFunction(data) {
  // cache data + some pre-calculations
  var cache = [];
  var i;
  for (i = 0; i < data.length; i++) {
    cache[i] = {};
    cache[i].valueMin = data[i].values[0];
    cache[i].valueMax = data[i].values[1];
    cache[i].rangeMin = i === 0 ? 0 : cache[i - 1].rangeMax;
    cache[i].rangeMax = cache[i].rangeMin + data[i].weight;
  }
  return function(random) {
    var value;
    for (i = 0; i < cache.length; i++) {
      // this maps random number to the bracket and the value inside that bracket
      if (cache[i].rangeMin <= random && random < cache[i].rangeMax) {
        value = (random - cache[i].rangeMin) / (cache[i].rangeMax - cache[i].rangeMin);
        value *= cache[i].valueMax - cache[i].valueMin + 1;
        value += cache[i].valueMin;
        return Math.floor(value);
      }
    }
  };
}

/*
 * Example usage
 */
var distributionFunction = createDistributionFunction([
  { weight: 0.1, values: [1, 40] },
  { weight: 0.8, values: [41, 60] },
  { weight: 0.1, values: [61, 100] }
]);

/*
 * Test the example and draw results using Google charts API
 */
function testAndDrawResult() {
  var counts = [];
  var i;
  var value;
  // run the function in a loop and count the number of occurrences of each value
  for (i = 0; i < 10000; i++) {
    value = distributionFunction(Math.random());
    counts[value] = (counts[value] || 0) + 1;
  }
  // convert results to datatable and display
  var data = new google.visualization.DataTable();
  data.addColumn("number", "Value");
  data.addColumn("number", "Count");
  for (value = 0; value < counts.length; value++) {
    if (counts[value] !== undefined) {
      data.addRow([value, counts[value]]);
    }
  }
  var chart = new google.visualization.ColumnChart(document.getElementById("chart"));
  chart.draw(data);
}
google.load("visualization", "1", { packages: ["corechart"] });
google.setOnLoadCallback(testAndDrawResult);
<script src="https://www.google.com/jsapi"></script>
<div id="chart"></div>


7

Đây là một giải pháp có trọng số ở 3/4 40-60 và 1/4 ngoài phạm vi đó.

function weighted() {

  var w = 4;

  // number 1 to w
  var r = Math.floor(Math.random() * w) + 1;

  if (r === 1) { // 1/w goes to outside 40-60
    var n = Math.floor(Math.random() * 80) + 1;
    if (n >= 40 && n <= 60) n += 40;
    return n
  }
  // w-1/w goes to 40-60 range.
  return Math.floor(Math.random() * 21) + 40;
}

function test() {
  var counts = [];

  for (var i = 0; i < 2000; i++) {
    var n = weighted();
    if (!counts[n]) counts[n] = 0;
    counts[n] ++;
  }
  var output = document.getElementById('output');
  var o = "";
  for (var i = 1; i <= 100; i++) {
    o += i + " - " + (counts[i] | 0) + "\n";
  }
  output.innerHTML = o;
}

test();
<pre id="output"></pre>


6

Ok, vì vậy tôi quyết định thêm một câu trả lời khác vì tôi cảm thấy giống như câu trả lời cuối cùng của mình, cũng như hầu hết các câu trả lời ở đây, sử dụng một số cách thống kê nửa để có được kết quả loại đường cong hình chuông. Mã tôi cung cấp dưới đây hoạt động tương tự như khi bạn lắc xí ngầu. Do đó, khó nhất là lấy 1 hoặc 99, nhưng dễ nhất là lấy 50.

var loops = 10; //Number of numbers generated
var min = 1,
    max = 50;
var div = $("#results").html(random());

function random() {
    var values = "";
    for (var i = 0; i < loops; i++) {
        var one = generate();
        var two = generate();
        var ans = one + two - 1;
        var num = values += ans + "<br/>";
    }
    return values;
}

function generate() {
    return Math.floor((Math.random() * (max - min + 1)) + min);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="results"></div>


6

Tôi khuyên bạn nên sử dụng bản phân phối beta để tạo một số trong khoảng 0-1, sau đó mở rộng nó. Nó khá linh hoạt và có thể tạo ra nhiều hình dạng phân phối khác nhau.

Đây là một bộ lấy mẫu nhanh và bẩn:

rbeta = function(alpha, beta) {
 var a = 0   
 for(var i = 0; i < alpha; i++)   
    a -= Math.log(Math.random())

 var b = 0   
 for(var i = 0; i < beta; i++)   
    b -= Math.log(Math.random())

  return Math.ceil(100 * a / (a+b))
}

5
var randNum;
// generate random number from 1-5
var freq = Math.floor(Math.random() * (6 - 1) + 1);
// focus on 40-60 if the number is odd (1,3, or 5)
// this should happen %60 of the time
if (freq % 2){
    randNum = Math.floor(Math.random() * (60 - 40) + 40);
}
else {
    randNum = Math.floor(Math.random() * (100 - 1) + 1);
}

5

Giải pháp tốt nhất nhắm đến chính vấn đề này là giải pháp được đề xuất bởi BlueRaja - Daniel Pflughoeft nhưng tôi nghĩ rằng một giải pháp nhanh hơn và tổng quát hơn cũng đáng được đề cập.


Khi tôi phải tạo số ngẫu nhiên (chuỗi, cặp tọa độ, v.v.) thỏa mãn hai yêu cầu của

  1. Tập kết quả khá nhỏ. (không lớn hơn 16K số)
  2. Bộ kết quả là kín đáo. (chỉ như số nguyên)

Tôi thường bắt đầu bằng cách tạo một mảng số (chuỗi, cặp tọa độ, v.v.) để đáp ứng yêu cầu (Trong trường hợp của bạn: một mảng số chứa nhiều số có thể xảy ra nhiều lần.), Sau đó chọn một mục ngẫu nhiên của mảng đó. Bằng cách này, bạn chỉ phải gọi hàm ngẫu nhiên đắt tiền một lần cho mỗi mục.


1
Nếu bạn sắp hoàn thành một loạt các lựa chọn, bạn cũng có thể xáo trộn chúng sau đó. Sau đó, bạn có thể chỉ cần lấy chúng theo thứ tự cho đến khi bạn hết. Xáo trộn lần nữa nếu / khi bạn nhấn vào cuối danh sách.
Geobits

@Geobits Xáo trộn một danh sách là nhiệm vụ tốn nhiều tài nguyên hơn sau đó chọn ngẫu nhiên một trong các yếu tố của nó. Nó chỉ là một lựa chọn tốt nếu danh sách phải được dự đoán trước.
mg30rg

1
Nhưng bạn chỉ làm điều đó một lần cho mỗi chu kỳ của danh sách thay vì mỗi lần. Nếu bạn xử lý trước điều này (vì dù sao bạn cũng có một bước tiền xử lý, tôi cho rằng điều đó vẫn ổn), thì sẽ rất nhanh để có được mỗi số sau đó. Bạn có thể cải tổ bất cứ khi nào bạn có thời gian, hoặc biết rằng bạn sẽ không cần một số ngẫu nhiên một chút. Chỉ cần cung cấp nó như là một thay thế, cả hai đều có (dis) lợi thế.
Geobits

@Geobits Nếu bạn làm theo cách của bạn, các số "xác suất duy nhất" sẽ "rơi ra" và cho đến khi kết hợp lại, chúng không thể xuất hiện. (tức là nếu bạn mô phỏng việc ném hai con xúc xắc, bạn sẽ không có cơ hội nhỏ nhất để có được số 2 nhiều hơn hai lần.)
mg30rg

1
Đó là một lý do tốt hơn nhiều để không sử dụng nó, ngoại trừ các ứng dụng hiếm hoi không sao;)
Geobits

4

Phân phối

 5% for [ 0,39]
90% for [40,59]
 5% for [60,99]

Giải pháp

var f = Math.random();
if (f < 0.05) return random(0,39);
else if (f < 0.95) return random(40,59);
else return random(60,99);

Giải pháp chung

random_choose([series(0,39),series(40,59),series(60,99)],[0.05,0.90,0.05]);

function random_choose (collections,probabilities)
{
    var acc = 0.00;
    var r1 = Math.random();
    var r2 = Math.random();

    for (var i = 0; i < probabilities.length; i++)
    {
      acc += probabilities[i];
      if (r1 < acc)
        return collections[i][Math.floor(r2*collections[i].length)];
    }

    return (-1);
}

function series(min,max)
{
    var i = min; var s = [];
    while (s[s.length-1] < max) s[s.length]=i++;
    return s;
}

4

Bạn có thể sử dụng số ngẫu nhiên của người trợ giúp để tạo số ngẫu nhiên trong 40-60 hoặc 1-100:

// 90% of random numbers should be between 40 to 60.
var weight_percentage = 90;

var focuse_on_center = ( (Math.random() * 100) < weight_percentage );

if(focuse_on_center)
{
	// generate a random number within the 40-60 range.
	alert (40 + Math.random() * 20 + 1);
}
else
{
	// generate a random number within the 1-100 range.
	alert (Math.random() * 100 + 1);
}


4

Nếu bạn có thể sử dụng gaussianchức năng, sử dụng nó. Hàm này trả về số bình thường với average 0sigma 1 .

95% số này là trong average +/- 2*sigma. Của bạn average = 50, và sigma = 5như vậy

randomNumber = 50 + 5*gaussian()

3

Cách tốt nhất để làm điều đó là tạo một số ngẫu nhiên được phân phối đều trong một tập hợp số nhất định, sau đó áp dụng hàm chiếu cho tập từ 0 đến 100 trong đó phép chiếu có nhiều khả năng đạt các số bạn muốn.

Thông thường, cách toán học để đạt được điều này là vẽ một hàm xác suất của các số bạn muốn. Chúng ta có thể sử dụng đường cong hình chuông, nhưng để tính toán dễ dàng hơn, chỉ cần làm việc với một parabol lật.

Chúng ta hãy tạo một parabol sao cho gốc của nó ở 0 và 100 mà không làm lệch nó. Chúng ta có phương trình sau:

f(x) = -(x-0)(x-100) = -x * (x-100) = -x^2 + 100x

Bây giờ, tất cả các khu vực dưới đường cong từ 0 đến 100 là đại diện cho tập đầu tiên của chúng tôi, nơi chúng tôi muốn các số được tạo. Ở đó, thế hệ hoàn toàn ngẫu nhiên. Vì vậy, tất cả những gì chúng ta cần làm là tìm giới hạn của tập đầu tiên.

Tất nhiên, giới hạn dưới là 0. Giới hạn trên là tích phân của hàm số 100 của chúng tôi, đó là

F(x) = -x^3/3 + 50x^2
F(100) = 500,000/3 = 166,666.66666 (let's just use 166,666, because rounding up would make the target out of bounds)

Vì vậy, chúng tôi biết rằng chúng tôi cần tạo một số ở đâu đó trong khoảng từ 0 đến 166.666. Sau đó, chúng ta chỉ cần lấy số đó và chiếu nó vào tập thứ hai, nằm trong khoảng từ 0 đến 100.

Chúng tôi biết rằng số ngẫu nhiên chúng tôi tạo ra là một số tích phân của parabol của chúng tôi với đầu vào x trong khoảng từ 0 đến 100. Điều đó có nghĩa là chúng tôi chỉ cần giả sử rằng số ngẫu nhiên là kết quả của F (x) và giải cho x.

Trong trường hợp này, F (x) là một phương trình bậc ba và ở dạng F(x) = ax^3 + bx^2 + cx + d = 0, các phát biểu sau là đúng:

a = -1/3
b = 50
c = 0
d = -1 * (your random number)

Việc giải quyết điều này cho x mang lại cho bạn số ngẫu nhiên thực tế mà bạn đang tìm kiếm, được đảm bảo nằm trong phạm vi [0, 100] và khả năng ở gần trung tâm cao hơn nhiều so với các cạnh.


3

Câu trả lời này thực sự tốt . Nhưng tôi muốn đăng các hướng dẫn triển khai (tôi không vào JavaScript, vì vậy tôi hy vọng bạn sẽ hiểu) cho các tình huống khác nhau.


Giả sử bạn có phạm vi và trọng lượng cho mọi phạm vi:

ranges - [1, 20], [21, 40], [41, 60], [61, 100]
weights - {1, 2, 100, 5}

Thông tin tĩnh ban đầu, có thể được lưu trữ:

  1. Tổng tất cả các trọng số (108 trong mẫu)
  2. Phạm vi lựa chọn phạm vi. Về cơ bản, công thức này: Boundary[n] = Boundary[n - 1] + weigh[n - 1]Boundary[0] = 0. Mẫu cóBoundary = {0, 1, 3, 103, 108}

Tạo số:

  1. Tạo số ngẫu nhiên Ntừ phạm vi [0, Tổng tất cả các trọng số).
  2. for (i = 0; i < size(Boundary) && N > Boundary[i + 1]; ++i)
  3. Lấy iphạm vi thứ và tạo số ngẫu nhiên trong phạm vi đó.

Lưu ý bổ sung cho tối ưu hóa hiệu suất. Phạm vi không phải được sắp xếp theo thứ tự không tăng dần hoặc giảm dần, vì vậy, để phạm vi tìm kiếm nhanh hơn có trọng lượng cao nhất nên đi trước và một phạm vi có trọng lượng thấp nhất nên đi sau.

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.