javascript - केंद्र पर केंद्रित एक यादृच्छिक संख्या प्राप्त करें




algorithm random (14)

आप 40-60 या 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);
}

क्या 1-100 के बीच एक यादृच्छिक संख्या प्राप्त करना और परिणाम मुख्य रूप से 40-60 सीमा के भीतर रखना संभव है? मेरा मतलब है, यह शायद ही कभी उस सीमा से बाहर जाएगा, लेकिन मैं चाहता हूं कि यह मुख्य रूप से उस सीमा के भीतर हो ... क्या यह जावास्क्रिप्ट / jQuery के साथ संभव है?

अभी मैं केवल मूल Math.random() * 100 + 1 का उपयोग कर रहा हूँ।


आप एक फ़ंक्शन लिख सकते हैं जो वजन के अनुसार [0, 1) से [1, 100] बीच यादृच्छिक मानों को मैप करता है। इस उदाहरण पर विचार करें:

यहाँ, [61, 100] बीच के मान के लिए 0.95 नक्शे हैं।
वास्तव में हमारे पास .05 / .1 = 0.5 , जो, जब [61, 100] मैप किया जाता है, तो पैदावार 81

यहाँ समारोह है:

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


इस तरह से कुछ का उपयोग करने के बारे में:

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>

जिस तरह से मैंने इसे कोडित किया है वह आपको कुछ प्रकार के चर सेट करने की अनुमति देता है:
छोरों = परिणामों की संख्या
कोशिश करता है = फ़ंक्शन को लूप के माध्यम से चलने से पहले 40-60 के बीच एक संख्या प्राप्त करने का प्रयास करने की संख्या

जोड़ा गया बोनस: यह उपयोग करता है जबकि !!! अपने सबसे अच्छे रूप में सजगता


इस समस्या को लक्षित करने वाला सबसे अच्छा समाधान ब्लूराज द्वारा प्रस्तावित एक है - डैनी पफ्लुघोफ्ट लेकिन मुझे लगता है कि कुछ हद तक तेज और अधिक सामान्य समाधान भी ध्यान देने योग्य है।

जब मुझे रैंडम नंबर्स (स्ट्रिंग्स, कोऑर्डिनेट पेयर वगैरह) जेनरेट करने होते हैं, तो दोनों की जरूरतों को पूरा करता है

  1. परिणाम सेट काफी छोटा है। (16K संख्या से बड़ा नहीं)
  2. परिणाम सेट विवेकपूर्ण है। (केवल पूर्णांक संख्याओं की तरह)

मैं आम तौर पर आवश्यकता को पूरा करने वाले संख्याओं (स्ट्रिंग्स, समन्वय जोड़े आदि) की एक सरणी बनाकर शुरू करता हूं (आपके मामले में: कई बार अधिक संभावित वाले संख्याओं की एक सरणी।), फिर उस सरणी का एक यादृच्छिक आइटम चुनें। इस तरह, आपको केवल प्रति आइटम एक बार महंगे यादृच्छिक फ़ंक्शन को कॉल करना होगा।


ऐसे यादृच्छिक संख्याओं को उत्पन्न करने के लिए कई अलग-अलग तरीके हैं। ऐसा करने का एक तरीका यह है कि एक समान रूप से यादृच्छिक संख्याओं के योग की गणना करें। आप कितने रैंडम नंबर लेते हैं और उनकी सीमा क्या है, यह निर्धारित करेगा कि अंतिम वितरण कैसा दिखेगा।

आप जितनी अधिक संख्या में योग करेंगे, उतना ही यह केंद्र की ओर से पक्षपाती होगा। आपके प्रश्न में 1 यादृच्छिक संख्या का योग पहले से ही प्रस्तावित था, लेकिन जैसा कि आप नोटिस करते हैं कि सीमा के केंद्र के लिए पक्षपाती नहीं है। अन्य उत्तरों में 2 यादृच्छिक संख्याओं या 3 यादृच्छिक संख्याओं के योग का उपयोग करने का प्रस्ताव है।

आप अधिक यादृच्छिक संख्याओं का योग लेकर सीमा के केंद्र की ओर और भी अधिक पूर्वाग्रह प्राप्त कर सकते हैं। चरम पर आप 99 यादृच्छिक संख्याओं का योग ले सकते हैं जो प्रत्येक 0 या 1 थे। यह एक द्विपद वितरण होगा। (द्विपद वितरण कुछ अर्थों में सामान्य वितरण के असतत संस्करण के रूप में देखा जा सकता है)। यह अभी भी सिद्धांत में पूरी श्रृंखला को कवर कर सकता है, लेकिन इसमें केंद्र के प्रति इतना पूर्वाग्रह है कि आपको इसे अंतिम बिंदु तक पहुंचने की उम्मीद नहीं करनी चाहिए।

इस दृष्टिकोण का मतलब है कि आप बस इतना पूर्वाग्रह कर सकते हैं कि आप कितना पूर्वाग्रह चाहते हैं।


ठीक है, इसलिए मैंने एक और उत्तर जोड़ने का फैसला किया क्योंकि मुझे अपना अंतिम उत्तर पसंद था, साथ ही साथ अधिकांश उत्तर भी, किसी तरह के आधे-सांख्यिकीय तरीके का उपयोग करके घंटी-वक्र प्रकार के परिणाम वापसी प्राप्त करते हैं। नीचे दिया गया कोड उसी तरह से काम करता है, जब आप पासा पलटते हैं। इसलिए, 1 या 99 प्राप्त करना सबसे कठिन है, लेकिन 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>


मैं बीटा वितरण का उपयोग कर 0-1 के बीच एक संख्या उत्पन्न करने की सलाह दूंगा, फिर इसे स्केल करूंगा। यह काफी लचीला है और वितरण के कई अलग-अलग आकार बना सकता है।

यहाँ एक त्वरित और गंदा नमूना है:

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

मैं "सीमा से बाहर" जाने की अनुमति के लिए कुछ "सेटअप" जैसा कुछ कर सकता हूं। इस उदाहरण में, 20% संभावना संख्या 1-100 होगी, अन्यथा, 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>

फिडल: http://jsfiddle.net/kbv39s9w/


यदि आप gaussian फ़ंक्शन का उपयोग कर सकते हैं, तो इसका उपयोग करें। यह फ़ंक्शन average 0 और sigma 1 साथ सामान्य संख्या देता है।

इस संख्या का 95% average +/- 2*sigma भीतर है। आपका average = 50 , और sigma = 5 तो

randomNumber = 50 + 5*gaussian()

यह बेवकूफ लग रहा है लेकिन आप दो बार रैंड का उपयोग कर सकते हैं:

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

वितरण

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

उपाय

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

सामान्य समाधान

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

संख्याओं की सरणियाँ लेना, आदि कुशल नहीं है। आपको एक मैपिंग लेनी चाहिए जो 0 से 100 के बीच एक यादृच्छिक संख्या लेती है और आपके द्वारा आवश्यक वितरण के लिए मैप करती है। तो आपके मामले में, आप अपनी श्रेणी के मध्य में सबसे अधिक मान के साथ वितरण प्राप्त करने के लिए f(x)=-(1/25)x 2 +4x ले सकते हैं।


यह उत्तर वास्तव में अच्छा है । लेकिन मैं विभिन्न निर्देशों के लिए कार्यान्वयन निर्देश (मैं जावास्क्रिप्ट में नहीं हूं, इसलिए मुझे आशा है कि आप समझ जाएंगे) पोस्ट करना चाहेंगे।

मान लें कि आपके पास हर रेंज के लिए रेंज और वज़न है:

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

प्रारंभिक स्टेटिक सूचना, कैश की जा सकती है:

  1. सभी भार का योग (नमूने में 108)
  2. सीमा चयन सीमाएँ। यह मूल रूप से यह सूत्र है: Boundary[n] = Boundary[n - 1] + weigh[n - 1] और Boundary[0] = 0 । नमूना की Boundary = {0, 1, 3, 103, 108}

संख्या पीढ़ी:

  1. श्रेणी [0, सभी भार के योग) से यादृच्छिक संख्या N उत्पन्न करें।
  2. for (i = 0; i < size(Boundary) && N > Boundary[i + 1]; ++i)
  3. i सीमा लेता i और उस श्रेणी में यादृच्छिक संख्या उत्पन्न करता i

प्रदर्शन अनुकूलन के लिए अतिरिक्त नोट। सीमाओं को न तो चढ़ते और न ही अवरोही क्रम का आदेश देना पड़ता है, इसलिए तेज गति वाली लुक-अप रेंज के लिए जिसमें सबसे अधिक वजन होना चाहिए, सबसे पहले जाना चाहिए और सबसे कम वजन वाले व्यक्ति को अंतिम बार जाना चाहिए।


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





numbers