"Acak" mudah untuk diminta dan ternyata mudah untuk salah. Perbedaan antara generator yang dapat Anda percayai untuk undian dan generator yang secara diam-diam mendukung angka-angka tertentu terletak pada beberapa gagasan: dari mana asal keacakan itu, bagaimana hal itu dipetakan ke dalam jangkauan Anda, dan apakah Anda ingin undian tersebut tidak dapat diprediksi atau dapat direproduksi. Generator ini dibuat berdasarkan perbedaan tersebut — aman secara kriptografis secara default, tidak memihak dalam konstruksi, dengan mode unggulan opsional ketika pengulangan lebih penting daripada kerahasiaan. Bagian di bawah ini menjelaskan apa yang terjadi dan cara memilih pengaturan yang tepat.

Acak sejati vs. acak semu

Ada dua kelompok keacakan. Generator angka acak yang sebenarnya (atau perangkat keras) menghasilkan ketidakpastian dari proses fisik — kebisingan listrik, jitter waktu, peluruhan radioaktif. Generator acak semu (PRNG) menjalankan rumus deterministik yang dimulai dari benih; keluarannya terlihat acak dan lulus uji statistik, namun keseluruhan rangkaiannya tetap setelah Anda mengetahui benihnya.

Browser Anda menjembatani keduanya. crypto.getRandomValues — sumber yang digunakan alat ini secara default — adalah PRNG yang aman secara kriptografis yang terus-menerus di-reseed dari kumpulan entropi perangkat keras sistem operasi. Untuk tujuan praktis, keluarannya tidak dapat diprediksi dan tidak memihak, itulah sebabnya ini adalah alat yang tepat untuk undian, token keamanan, dan apa pun yang memungkinkan seseorang mendapatkan keuntungan dengan menebak nilai berikutnya. Math.random yang lama adalah PRNG biasa tanpa jaminan keamanan dan sengaja tidak digunakan di sini.

Bias modulo, dan mengapa pengambilan sampel penolakan memperbaikinya

Ini adalah kesalahan yang dilakukan sebagian besar kode acak buatan sendiri. Untuk mengubah bilangan acak besar menjadi, katakanlah, bilangan dari 1 sampai 6, langkah yang jelas adalah sisanya: 1 + (x mod 6). Masalahnya adalah sumber mempunyai kemungkinan nilai 2³², dan 2³² tidak habis dibagi 6. Nilai sisa di bagian atas rentang melingkari dan mendarat pada beberapa hasil pertama, menjadikan 1, 2, 3, dan 4 sangat kecil kemungkinannya dibandingkan 5 dan 6. Dengan dadu bersisi enam, kemiringannya kecil; dengan rentang yang besar, atau lebih dari jutaan penarikan, hal ini menjadi dapat diukur — dan dalam konteks keamanan, hal ini merupakan kelemahan yang nyata.

Perbaikannya adalah pengambilan sampel penolakan: hitung kelipatan terbesar dari rentang Anda yang sesuai dengan 2³², ambil nilai mentah, dan buang semua nilai tersebut ke keranjang sisa sebelum mengambil sisanya. Beberapa hasil seri akan dibuang, tetapi setiap bilangan bulat dalam rentang Anda memiliki kemungkinan yang sama persis. Generator ini melakukan hal tersebut untuk setiap bilangan bulat yang dihasilkannya, jadi “1–6” adalah dadu yang adil dan “1–10.000” adalah dadu yang seragam.

Pilihan lotere yang unik vs. berulang, dan adil

Pengundian “Izinkan pengulangan” dengan penggantian: setiap pengambilan bersifat independen, sehingga angka yang sama dapat muncul lebih dari satu kali — model yang tepat untuk pelemparan dadu dan koin. Pengundian “Unik” tanpa pengembalian: setiap nilai muncul paling banyak satu kali, yang merupakan nilai yang Anda inginkan untuk undian, pemilihan tim, atau garis lotere. Saat Anda meminta nilai unik, generator akan mengacak kumpulan yang memenuhi syarat dengan pengacakan parsial Fisher–Yates dan mengambil k pertama, yang menjaga kemungkinan setiap kombinasi tetap sama dan menjamin tidak ada duplikat.

Dua pagar pembatas penting di sini. Anda tidak dapat menggambar lebih banyak nilai unik daripada yang ada dalam rentang — meminta 10 angka unik dari 1–6 adalah hal yang mustahil, jadi alat ini akan menarik semua yang bisa dilakukan dan memperingatkan Anda. Dan daftar pengecualian menghapus nilai tertentu (pemenang yang sudah ditarik, 13 yang tidak beruntung) dari kumpulan sebelum pengundian, yang juga menyusutkan kumpulan unik.

Kapan menggunakan benih (reprodusibilitas)

Sering kali Anda menginginkan keacakan yang tidak dapat Anda prediksi, sehingga mode keamanan kripto default sudah benar. Namun terkadang Anda menginginkan kebalikan: hasil imbang yang dapat Anda ulangi sesuai permintaan. Itulah gunanya benih itu. Dalam mode Seeded, angkanya berasal dari mulberry32, PRNG deterministik, dan seed yang sama dengan pengaturan yang sama selalu menghasilkan angka yang sama.

Ini benar-benar berguna. Seorang peneliti dapat mempublikasikan benih tersebut bersamaan dengan penelitian sehingga sampel acak dapat direproduksi. Tuan rumah undian dapat mengumumkan benihnya terlebih dahulu sehingga peserta dapat memverifikasi undian setelahnya alih-alih mempercayainya. Pengembang dapat menyemai data pengujian sehingga pengujian yang gagal dapat diulangi. Keuntungannya adalah urutan yang diunggulkan, secara desain, dapat diprediksi oleh siapa saja yang mengetahui urutan tersebut — jadi jangan pernah menggunakan mode unggulan untuk membuat sandi, kunci, atau apa pun yang harus tetap dirahasiakan.

Apakah ini adil? Membaca distribusinya

“Apakah ini benar-benar acak?” adalah pertanyaan yang wajar, dan tab Statistik ada untuk menjawabnya. Untuk satu undian kecil, Anda tidak dapat mengetahui banyak — lima angka dari 1–100 tidak akan terlihat berjarak sama, dan itu normal; keacakan yang sebenarnya itu kental, tidak rapi. Polanya hanya muncul dalam skala besar. Pelemparan dadu beberapa ratus kali, atau buat sampel dalam jumlah besar, dan bilah frekuensi akan rata ke ketinggian yang sama, yang merupakan ciri visual dari distribusi yang seragam.

Ini juga merupakan penawar dari kekeliruan penjudi. Perputaran lima kepala tidak menjadikan ekor “jatuh tempo” — setiap pelemparan bersifat independen dan tetap 50/50, dan penghitungan lari hanya bergerak menuju 50% seiring dengan bertambahnya jumlah pelemparan (hukum bilangan besar), tanpa ada satu pelemparan yang dipengaruhi oleh pelemparan sebelumnya.