Kā es varu ģenerēt nejaušus veselus skaitļus starp diviem norādītajiem mainīgajiem JavaScript, piemēram, x = 4
un y = 8
, lai izvadītu jebkuru no 4, 5, 6, 6, 7, 8
?
Daži piemēri ir atrodami Mozilla Developer Network lapā:
/**
* 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).
* The value is no lower than min (or the next integer greater than min
* if min isn't an integer) and no greater than max (or the next integer
* lower than max if max isn't an integer).
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Lūk, kāda ir tā loģika. Tas ir vienkāršs trīs likums:
Math.random()
atgriež skaitli
starp 0 (ieskaitot) un 1 (izslēdzot). Tātad mums ir šāds intervāls:
[0 .................................... 1)
Tagad mēs vēlamies skaitli starp min
(ieskaitot) un max
(izslēdzot):
[0 .................................... 1)
[min .................................. max)
Mēs varam izmantot Math.random
, lai iegūtu atbilstošo skaitli intervālā [min, max]. Bet vispirms mums vajadzētu mazliet izlīdzināt problēmu, atņemot min
no otrā intervāla:
[0 .................................... 1)
[min - min ............................ max - min)
Tādējādi iegūstam:
[0 .................................... 1)
[0 .................................... max - min)
Tagad varam izmantot Math.random
un aprēķināt atbilstošo. Izvēlēsimies nejaušu skaitli:
Math.random()
|
[0 .................................... 1)
[0 .................................... max - min)
|
x (what we need)
Tātad, lai atrastu x
, mēs izdarītu:
x = Math.random() * (max - min);
Neaizmirstiet pievienot atpakaļ min
, lai iegūtu skaitli intervālā [min, max]:
x = Math.random() * (max - min) + min;
Tā bija pirmā funkcija no MDN. Otrā atgriež veselu skaitli starp min
un max
, abus ieskaitot.
Lai iegūtu veselos skaitļus, var izmantot round
, ceil
vai floor
.
Varētu izmantot Math.round(Math.random() * (max - min)). + min
, tomēr tas dod nevienmērīgu sadalījumu. Gan min
, gan max
ir tikai aptuveni puse no izlozes iespējām:
min...min+0.5...min+1...min+1.5 ... max-0.5....max
└───┬───┘└────────┬───────┘└───── ... ─────┘└───┬──┘ ← Math.round()
min min+1 max
Izslēdzot max
no intervāla, tam ir vēl mazāka izredzes izkrīt nekā min
.
Ar Math.floor(Math.random() * (max - min +1)) + min
ir pilnīgi vienmērīgs sadalījums.
min.... min+1... min+2 ... max-1... max.... max+1 (is excluded from interval)
| | | | | |
└───┬───┘└───┬───┘└─── ... ┘└───┬───┘└───┬───┘ ← Math.floor()
min min+1 max-1 max
Šajā vienādojumā nevar izmantot ceil()
un -1
, jo max
tagad bija nedaudz mazāka iespēja, bet var izspēlēt arī (nevēlamo) min-1
rezultātu.
function getRandomizer(bottom, top) {
return function() {
return Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom;
}
}
izmantošana:
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.
}
sadalījums:
Mēs atgriežam funkciju (aizgūtu no funkcionālās programmēšanas), kas pēc izsaukuma atgriež nejaušu veselu skaitli starp vērtībām bottom
un top
, ieskaitot. Mēs sakām "ieskaitot", jo vēlamies, lai atgriezto skaitļu diapazonā būtu gan bottom, gan top. Tādējādi getRandomizer( 1, 6 )
atgriezīs 1, 2, 3, 4, 5 vai 6.
(apakšējais skaitlis ir mazāks skaitlis, augšējais skaitlis ir lielāks skaitlis).
Math.random() * ( 1 + top - bottom )
Math.random()
atgriež nejaušu divkāršu skaitli starp 0 un 1, un, ja to reizināsim ar vienu plus starpību starp augšējā
un apakšējā
, iegūsim divkāršu skaitli kaut kur starp 0
un 1+b-a
.
Math.floor( Math.random() * ( 1 + top - bottom ) )
Math.floor
noapaļo skaitli uz leju līdz tuvākajam veselam skaitlim. Tātad tagad mums ir visi veseli skaitļi starp 0
un augšējā un apakšējā daļa
. 1 izskatās mulsinoši, bet tam ir jābūt, jo mēs vienmēr noapaļojam uz leju, tāpēc augšējais skaitlis bez tā nekad netiks sasniegts. Ģenerētajam nejaušajam decimālskaitlim jābūt no 0
līdz (1+top-bottom)
, lai mēs varētu noapaļot uz leju un iegūt int no 0
līdz top-bottom
.
Math.floor( Math.random() * ( 1 + top - bottom ) ) + bottom
Iepriekšējā piemērā dotais kods deva veselu skaitli diapazonā 0
un top-bottom
, tāpēc tagad mums tikai jāpievieno šim rezultātam bottom
, lai iegūtu veselu skaitli diapazonā no bottom
līdz top
ieskaitot :D :D
PIEZĪME: Ja vispirms nodosiet vērtību, kas nav vesels skaitlis, vai lielāku skaitli, jūs iegūsiet nevēlamu uzvedību, bet, ja neviens to nepieprasīs, es neiedziļināšos argumentu pārbaudes kodā, jo tas ir diezgan tālu no sākotnējā jautājuma nolūka.
function getRandomInt(lower, upper)
{
//to create an even sample distribution
return Math.floor(lower + (Math.random() * (upper - lower + 1)));
//to produce an uneven sample distribution
//return Math.round(lower + (Math.random() * (upper - lower)));
//to exclude the max value from the possible values
//return Math.floor(lower + (Math.random() * (upper - lower)));
}
Lai pārbaudītu šo funkciju un tās variācijas, saglabājiet zemāk redzamo HTML/JavaScript failā un atveriet to pārlūkprogrammā. Kods izveidos grafiku, kurā būs redzams viena miljona funkcijas izsaukumu sadalījums. Kods reģistrēs arī malējos gadījumus, tāpēc, ja funkcija radīs vērtību, kas ir lielāka par maksimālo vai mazāka par minimālo, jūs.par.to.uzzināsiet.
<html>
<head>
<script type="text/javascript">
function getRandomInt(lower, upper)
{
//to create an even sample distribution
return Math.floor(lower + (Math.random() * (upper - lower + 1)));
//to produce an uneven sample distribution
//return Math.round(lower + (Math.random() * (upper - lower)));
//to exclude the max value from the possible values
//return Math.floor(lower + (Math.random() * (upper - lower)));
}
var min = -5;
var max = 5;
var array = new Array();
for(var i = 0; i <= (max - min) + 2; i++) {
array.push(0);
}
for(var i = 0; i < 1000000; i++) {
var random = getRandomInt(min, max);
array[random - min + 1]++;
}
var maxSample = 0;
for(var i = 0; i < max - min; i++) {
maxSample = Math.max(maxSample, array[i]);
}
//create a bar graph to show the sample distribution
var maxHeight = 500;
for(var i = 0; i <= (max - min) + 2; i++) {
var sampleHeight = (array[i]/maxSample) * maxHeight;
document.write('<span style="display:inline-block;color:'+(sampleHeight == 0 ? 'black' : 'white')+';background-color:black;height:'+sampleHeight+'px"> [' + (i + min - 1) + ']: '+array[i]+'</span> ');
}
document.write('<hr/>');
</script>
</head>
<body>
</body>
</html>