1. Nomor pseudorandom

Terkadang seorang pemrogram menghadapi tugas yang tampaknya sederhana: "pilih film acak dari daftar tertentu", "pilih pemenang lotre", "acak daftar putar saat pengguna mengguncang ponsel cerdasnya", "pilih nomor acak untuk mengenkripsi pesan" , dll. Dalam setiap kasus, pengembang mengajukan pertanyaan logis: bagaimana cara mendapatkan nomor acak?

Sebenarnya mendapatkan angka yang benar-benar acak agak sulit dilakukan. Nyatanya, sangat sulit sehingga koprosesor matematika khusus dibangun di beberapa komputer untuk menghasilkan angka yang memenuhi semua persyaratan keacakan yang sebenarnya.

Pemrogram datang dengan solusi mereka sendiri: nomor pseudorandom . Angka pseudorandom adalah sejenis urutan, yang angkanya tampak acak. Namun, dengan melakukan analisis yang cermat, seorang ahli dapat menemukan pola-pola tertentu dalam urutan tersebut. Nomor seperti itu tidak cocok untuk mengenkripsi dokumen rahasia, tetapi cukup untuk mensimulasikan lemparan dadu dalam permainan.

Ada banyak algoritma untuk menghasilkan urutan bilangan acak semu. Hampir semuanya menghasilkan nomor acak berikutnya berdasarkan nomor sebelumnya dan beberapa nomor pembantu tambahan.

Misalnya, program ini akan menampilkan 1000angka yang tidak berulang:

public class Main
{
   public static int a = 41;
   public static int c = 11119;
   public static int m = 11113;
   public static int seed = 1;

   public static int getNextRandom()
   {
     seed = (a * seed + c) % m;
     return seed;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 1000; i++)
     {
       System.out.println(getNextRandom());
     }
   }
}

Omong-omong, kita tidak berbicara tentang angka pseudorandom di sini. Kita berbicara tentang urutan nomor pseudorandom. Melihat satu nomor, tidak mungkin untuk mengetahui apakah itu acak atau tidak.

Memang, ada berbagai cara untuk mendapatkan nomor acak:

public static int getRandomNumber()
{
   return 4; // Here's a random number (we got it by rolling a die)
}

2.Math.random()

Di Java, Mathkelas memiliki metode khusus yang mengembalikan angka acak. Dan seperti yang Anda duga, metode ini disebut random. Secara umum, inilah cara memanggil metode ini:

Math.random()

Metode ini tidak memerlukan parameter dan mengembalikan bilangan real pseudorandom dalam rentang dari 0hingga 1. Angka 1 sendiri tidak termasuk dalam rentang tersebut.

Contoh:

Kode Keluaran konsol
public class Main
{
   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       System.out.println(Math.random());
     }
   }
}
0.9703753971734451
0.09979423801773157
0.994048474709053
0.2852203204171295
0.13551248551226025
0.3128547131272822
0.5342480554101412
0.6817369932044817
0.1840767788961758
0.06969563435451254

Tetapi bagaimana jika metode ini tidak sesuai dengan yang Anda butuhkan? Misalkan, Anda ingin menulis program yang mensimulasikan penggulingan dadu bersisi enam. Bagaimana Anda mendapatkan bilangan bulat acak dalam rentang 1..6, bukan bilangan real dalam rentang 0..1?

Ini sebenarnya cukup sederhana.

Pertama, Anda perlu memetakan rentang [0, 1)ke [0, 6). Untuk melakukannya, kalikan saja hasil yang dikembalikan random()oleh 6. Tentu saja, untuk mendapatkan bilangan bulat, Anda perlu membulatkan:

Kode Keluaran konsol
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6);
   }

   public static void main(String[] args)
   {
      for (int i = 0; i < 10; i++)
      {
         int x = getRandomDieNumber();
         System.out.println(x);
      }
   }
}
5
2
3
3
2
4
1
1
5
0

Mengembalikan getRandomDieNumber()bilangan bulat acak dalam kisaran 0..5inklusif. Tapi itu tidak akan menjadi nomor di set 1, 2, 3, 4, 5, 6. Ini akan menjadi nomor di set 0, 1, 2, 3, 4, 5.

Jika yang Anda butuhkan adalah angka di set 1, 2, 3, 4, 5, 6, maka tambahkan saja satu ke angka acak:

Kode Keluaran konsol
public class Main
{
   public static int getRandomDieNumber()
   {
      return (int) (Math.random() * 6) + 1;
   }

   public static void main(String[] args)
   {
     for (int i = 0; i < 10; i++)
     {
       int x = getRandomDieNumber();
       System.out.println(x);
     }
   }
}
3
2
1
3
6
5
6
1
6
6

Nah, itu sempurna!



3. Randomkelas

Java memiliki Randomkelas khusus yang merangkum urutan angka pseudorandom. Anda dapat membuat beberapa objek kelas Random. Masing-masing objek ini akan menghasilkan urutan nomor pseudorandomnya sendiri.

Ini adalah kelas yang sangat menarik dengan banyak metode menarik. Mari kita mulai dengan yang paling sederhana.

double nextDouble()

Metode ini mengembalikan bilangan real acak dalam rentang 0.0- 1.0. Ini sangat mirip dengan metodenya Math.random(). Dan tidak heran, karena Math.random()metode tersebut hanya memanggil nextDouble()metode pada Randomobjek.

float nextFloat()

Metode ini sangat mirip dengan nextDouble()metode, tetapi nomor acak yang dikembalikan adalah float. Itu juga terletak pada kisaran 0.0- 1.0. Dan, seperti biasa di Jawa, range tidak termasuk angka itu 1.0sendiri.

Random r = new Random();
float f = r.nextFloat();

int nextInt(int max)

Metode ini mengembalikan bilangan bulat acak dalam range [0, max). 0termasuk dalam kisaran, tetapi maxtidak.

Dengan kata lain, jika Anda ingin mendapatkan nomor acak di set 1, 2, 3, 4, 5, 6, maka Anda perlu menambahkan satu ke nomor acak yang dikembalikan:

Random r = new Random();
int x = r.nextInt(6) + 1;

int nextInt()

Metode ini mirip dengan yang sebelumnya, tetapi tidak menggunakan parameter apa pun. Jadi berapa kisaran nilai pengembaliannya? Dari -2 billionke +2 billion.

Tepatnya, dari -2147483648ke +2147483647.

long nextLong()

Metode ini mirip dengan nextInt()metode, tetapi nilai pengembalian akan jatuh di suatu tempat di seluruh rentang longs yang mungkin.

boolean nextBoolean()

Metode ini mengembalikan booleannilai acak: falseatau true. Ini sangat nyaman ketika Anda perlu mendapatkan urutan panjang nilai boolean acak.

void nextBytes(byte[] data)

Metode ini tidak menghasilkan apa-apa (karena jenis pengembaliannya adalah void). Sebaliknya, itu mengisi array yang diteruskan dengan nilai acak. Ini sangat berguna saat Anda membutuhkan buffer besar yang diisi dengan data acak.

double nextGaussian()

Metode ini mengembalikan bilangan real acak dalam rentang 0.0- 1.0. Namun, jumlahnya tidak terdistribusi secara merata dalam kisaran ini. Sebaliknya, mereka mengikuti distribusi normal .

Nilai di dekat tengah rentang ( 0.5) akan muncul lebih sering daripada nilai di ujung rentang.

Kelas acak

Dalam kasus kami, puncak distribusi nilai akan berada di0.5