
🎲 Kuinka luoda satunnainen kokonaisluku tietyllä välillä JavaScriptillä
Satunnaislukuja tarvitaan kaikkialla. Tilausnumerot verkkokaupoissa, salasanan palautuskoodit, nopanheitot selainpeleissä, arvonnan voittajan valinta. Ja lähes aina kehittäjät kirjoittavat saman rivin: Math.random().
Mutta "satunnainen desimaaliluku 0:sta 1:een" ja "satunnainen kokonaisluku 5:stä 20:een" välillä on kolmen operaation kuilu, jossa aloittelijat tekevät säännöllisesti virheitä: Math.floor ja Math.ceil, plus yksi vai ei plussaa, hämmennystä, joka johtaa joko alueen ylivuotoon tai epätasaiseen jakaumaan.
Puretaan kaava viimeistä sulkua myöten, kirjoitetaan toimiva generaattori puhtaalla HTML+CSS+JS:llä ja katsotaan, missä Math.random() jää vajaaksi.
💡 Pikakatsaus:
- Pura kaava Math.floor(Math.random() * (max - min + 1)) + min, ymmärrä jokainen operaatio.
- Opi, miksi vain Math.floor toimii, ei Math.ceil tai Math.round, esimerkkeinä alueen vääristymät.
- Kopioi valmis HTML-generaattori: kaksi kenttää, painike, tulosteen näyttö, puhdas JS, ei frameworkeja.
- Hallitse Crypto.getRandomValues, kun Math.random ei sovellu ja tarvitset kryptografisesti turvallisen vaihtoehdon.
Miten Math.random() toimii
Math.random() on sisäänrakennetun Math-olion staattinen metodi. Se ei ota argumentteja ja palauttaa pseudo-satunnaisen liukuluvun väliltä [0, 1) MDN-määrittelyn mukaisesti. Hakasulje nollan kohdalla tarkoittaa "sisältäen", kaarisulje ykkösen kohdalla "pois lukien". Voit siis saada 0.0, arvon noin 0.372 tai jotain lähellä 0.999, mutta et koskaan tarkalleen 1.0.
Jakauma on likimain tasainen. Toteutus on sisäänrakennettu moottoriin (V8, SpiderMonkey, JavaScriptCore), eikä kehittäjä voi valita tai nollata tiettyä algoritmia (yleensä xorshift128+); siemenen asettaa moottori käynnistyksen yhteydessä.
Sellaisenaan Math.random() on hyödytön käytännön tehtäviin. Pelit tarvitsevat kokonaislukuja, arpajaiset kokonaislukuja tietyltä väliltä, kryptografia tarvitsee kryptografisesti turvallista entropiaa, jota Math.random() ei tarjoa. Siksi sen ympärille kiedotaan aina alueen muunnoskaava.
Kaava: satunnainen kokonaisluku välillä [min, max]
Peruskaava, joka kattaa valtaosan tapauksista web-kehityksessä:
1 function randomInt(min, max) { 2 return Math.floor(Math.random() * (max - min + 1)) + min; 3 }
Puretaan se oppimisesimerkillä, jossa min = 5 ja max = 10, perustuen Math.random-dokumentaatioon:
- Oletetaan, että
Math.random()palautti arvonRväliltä [0, 1). max - min + 1=10 - 5 + 1=6, mahdollisten kokonaislukutulosten määrä: 5, 6, 7, 8, 9, 10.R * 6skaalasi satunnaisen desimaalin alueen leveyteen.Math.floor(R * 6)pyöristi alaspäin hylkäämällä desimaaliosan. Nyt meillä on indeksi 0:sta 5:een.index + minsiirsimin:n verran. Valmis: satunnainen kokonaisluku 5:stä 10:een, molemmat mukaan lukien.
Sama kaava yksirivisenä:
1 const roll = Math.floor(Math.random() * (max - min + 1)) + min;
Miksi Math.floor, ei Math.ceil tai Math.round
Pyöristysmenetelmän valinta vaikuttaa kriittisesti jakaumaan. Havainnollistetaan oppimisesimerkillä käyttäen väliä 1:stä 3:een (kaikki arvot paitsi välin rajat on laskettu). Lähestymistapa on kuvattu kanonisessa StackOverflow-vastauksessa.
Käytettäessä Math.floor ja kaavaa (max - min + 1):
- Jos
Math.random()osuu välin [0, 1) ensimmäiseen kolmannekseen: kertominen 3:lla antaa arvon 0:sta lähes 1:een,Math.floorhylkää desimaaliosan, tuottaen indeksin 0, plusminantaa 1 (tasan yksi kolmasosa tapauksista). - Jos
Math.random()on keskimmäisessä kolmanneksessa: kertominen 3:lla antaa 1:stä lähes 2:een,Math.floor→ indeksi 1, plusmin→ 2 (toinen kolmasosa). - Jos
Math.random()on viimeisessä kolmanneksessa: kertominen 3:lla antaa 2:sta lähes 3:een,Math.floor→ indeksi 2, plusmin→ 3 (viimeinen kolmasosa).
Tasainen jakauma.
Mitä tapahtuu Math.ceil:llä? Math.ceil(Math.random() * 3) antaa 1, 2, 3, mutta 1:llä on mitätön mahdollisuus (vain kun Math.random() on tasan 0, mitä ei juuri koskaan tapahdu). Reuna-arvot vääristyvät.
Math.round on myös epätasainen: reuna-arvot saavat puolet keskimmäisten arvojen mahdollisuudesta. Siksi satunnaisten kokonaislukujen generointi käyttää yksinomaan Math.floor.
Täydellinen esimerkki: generaattori HTML:llä, CSS:llä ja JavaScriptillä
Toimiva sivu, jonka voit tallentaa .html-päätteellä ja avata selaimessa. Kaksi syötekenttää, painike, tulos vihreällä taustalla.
1 <!DOCTYPE html> 2 <html lang="ru"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Генератор случайных чисел</title> 6 <style> 7 body { 8 font-family: system-ui, sans-serif; 9 max-width: 400px; 10 margin: 50px auto; 11 padding: 0 16px; 12 } 13 label { 14 display: block; 15 margin-top: 12px; 16 font-weight: 600; 17 } 18 input { 19 width: 100%; 20 padding: 8px; 21 margin-top: 4px; 22 font-size: 16px; 23 box-sizing: border-box; 24 } 25 button { 26 margin-top: 16px; 27 padding: 10px 24px; 28 font-size: 16px; 29 cursor: pointer; 30 } 31 .result { 32 margin-top: 20px; 33 font-size: 24px; 34 font-weight: 700; 35 color: #2e7d32; 36 } 37 </style> 38 </head> 39 <body> 40 41 <h1>Случайное число в диапазоне</h1> 42 43 <label for="minInput">От:</label> 44 <input type="number" id="minInput" value="1"> 45 46 <label for="maxInput">До:</label> 47 <input type="number" id="maxInput" value="100"> 48 49 <button id="generateBtn">Сгенерировать</button> 50 51 <div class="result" id="resultDisplay"></div> 52 53 <script> 54 function randomInt(min, max) { 55 return Math.floor(Math.random() * (max - min + 1)) + min; 56 } 57 58 const minInput = document.getElementById('minInput'); 59 const maxInput = document.getElementById('maxInput'); 60 const generateBtn = document.getElementById('generateBtn'); 61 const resultDisplay = document.getElementById('resultDisplay'); 62 63 generateBtn.addEventListener('click', () => { 64 const min = parseInt(minInput.value, 10); 65 const max = parseInt(maxInput.value, 10); 66 67 if (isNaN(min) || isNaN(max)) { 68 resultDisplay.textContent = 'Введите оба числа'; 69 return; 70 } 71 if (min > max) { 72 resultDisplay.textContent = '«От» не может быть больше «До»'; 73 return; 74 } 75 76 const result = randomInt(min, max); 77 resultDisplay.textContent = `Результат: ${result}`; 78 }); 79 </script> 80 81 </body> 82 </html>
Koodi on tarkoituksella kirjoitettu puhtaalla JavaScriptillä, ilman frameworkeja tai paketointityökaluja, jotta sen voi kopioida ja ajaa heti ilman npm install -komentoa. randomInt-funktio ottaa min ja max, palauttaen kokonaisluvun, joka sisältää molemmat päät. Painikkeen käsittelijä lukee arvot kentistä, validoi ne ja näyttää tuloksen.
Kun Math.random() ei riitä: Crypto.getRandomValues()
Math.random() on pseudo-satunnaisgeneraattori. Se riittää peleihin, animaatioihin, A/B-testeihin ja satunnaisen taulukon alkion valintaan. Mutta tehtäviin, joissa ennustettavuus tarkoittaa haavoittuvuutta, se ei sovellu: salasanan palautustunnisteet, API-avaimet, kryptografiset noncet, kertakäyttöisten linkkien generaattorit.
Kuvittele: lähetät käyttäjälle salasanan palautuslinkin, jonka tunniste on generoitu Math.random():lla. Kun siemen ja algoritmi tunnetaan (ne ovat moottorille vakioita), hyökkääjä voi rekonstruoida sekvenssin ja arvata tunnisteen. Juuri siksi minkä tahansa tietoturvaan liittyvän koodin on käytettävä kryptografisesti turvallista satunnaisuuslähdettä.
Tällaisia skenaarioita varten on olemassa Web Crypto API: crypto.getRandomValues(). Se käyttää käyttöjärjestelmän kryptografisesti turvallista entropialähdettä ja täyttää annetun tyypitetyn taulukon satunnaisarvoilla.
Kryptografisesti turvallisen satunnaisen kokonaisluvun generointi tietyltä väliltä:
1 function secureRandomInt(min, max) { 2 const range = max - min + 1; 3 const maxSafeVal = Math.floor(256 ** 4 / range) * range; 4 const buffer = new Uint32Array(1); 5 6 do { 7 crypto.getRandomValues(buffer); 8 } while (buffer[0] >= maxSafeVal); 9 10 return min + (buffer[0] % range); 11 }
Tämä käyttää hylkäysotantaa: funktio pyytää satunnaista 32-bittistä arvoa ja hylkää ne, jotka osuvat tasaisesti jaollisen alueen ulkopuolelle. Tämä eliminoi modulo-harhan, jossa jotkin arvot esiintyvät useammin kuin toiset.
Käytännössä Math.random() riittää useimpiin verkkosovelluksiin. Mutta jos kirjoitat generaattoria kertakäyttölinkeille tai vahvistuskoodeille, käytä crypto.getRandomValues().
Video: satunnaisluvun generointi JavaScriptissä
Lyhyt demonstraatio dcode-kanavalta, jossa puretaan Math.random() ja aluekaava live-esimerkillä selaimen konsolissa:
⁉️🤔 Usein kysytyt kysymykset
Sisältääkö kaava Math.floor(Math.random() * (max - min + 1)) + min ylärajan?
Kyllä sisältää.
max - min + 1antaa mahdollisten kokonaislukutulosten määrän, jaMath.flooryhdistettynä+ minvarmistaa, ettämaxon saavutettavissa. Esimerkiksi arvoillamin=1, max=3saat 1, 2 tai 3; kaikki kolme arvoa ovat mahdollisia.
Voiko Math.ceil käyttää Math.floor sijasta?
Teknisesti kyllä, mutta jakaumasta tulee epätasainen. Kun käytetään
Math.ceil(Math.random() * range), arvominesiintyy vain, kunMath.random()palauttaa tasan 0, mikä on äärimmäisen harvinainen tapahtuma.Math.floorantaa jokaiselle välin kokonaisluvulle yhtä suuren mahdollisuuden, minkä vuoksi vakiokaava käyttää sitä.
Onko Math.random() todella satunnainen luku?
Ei, se on pseudo-satunnainen luku. JavaScript-moottori käyttää determinististä algoritmia (yleensä xorshift128+), joka tuottaa tilastollisesti tasaisen sekvenssin, mutta siemenen tunteminen mahdollistaa kaikkien myöhempien arvojen ennustamisen. Kryptografiaan tämä ei kelpaa; käytä
crypto.getRandomValues().
Miten generoidaan satunnainen liukuluku tietyltä väliltä?
Poista
Math.floorja+ 1:Math.random() * (max - min) + min. Tämä antaa desimaaliluvunmin:stä (mukaan lukien)max:iin (pois lukien). Jos tarvitset myös ylärajan mukaan, korvaamax - minlausekkeellamax - min + Number.EPSILON, mutta käytännössä desimaalivälit vaativat harvoin ylärajan sisällyttämistä.
Kumpi on nopeampi: Math.random() vai crypto.getRandomValues()?
Math.random()on kertaluokkia nopeampi. V8:n benchmarkeissa ero on satakertainen tai enemmän, koskacrypto.getRandomValues()tekee järjestelmäkutsun/dev/urandom(Linux) tai vastaavaan, kun taasMath.random()on puhtaasti prosessin sisäinen PRNG. Tuhansien arvojen generointiin silmukassa käytäMath.random(); yksittäiselle tietoturvatunnisteelle käytäcrypto.getRandomValues().
Satunnaisluku 30 sekunnissa: mitä muistaa
Työjuhta on Math.floor(Math.random() * (max - min + 1)) + min. Muista kolme sääntöä: aina Math.floor (ei ceil, ei round), aina + 1 kertoimessa (jotta max on saavutettavissa), aina + min lopussa (alueen siirtämiseksi). Nämä kolme operaatiota kattavat kaiken nopanheitoista satunnaisen voittajan valintaan.
Salasanan palautuskoodeihin ja tunnisteisiin käytä crypto.getRandomValues(). Hitaampi, mutta kryptografisesti turvallinen.
Jos haluat vain kokeilla, kopioi yllä oleva HTML-esimerkki, tallenna se tiedostona ja avaa selaimessa. Ei riippuvuuksia, ei paketointityökaluja. Toimii missä tahansa, missä on <script>.



