1. Số giả ngẫu nhiên

Đôi khi một lập trình viên phải đối mặt với những nhiệm vụ có vẻ đơn giản: "chọn một bộ phim ngẫu nhiên từ một danh sách nhất định", "chọn người trúng số", "xáo trộn danh sách phát khi người dùng lắc điện thoại thông minh của họ", "chọn một số ngẫu nhiên để mã hóa tin nhắn" , v.v. Trong mỗi trường hợp, nhà phát triển đặt một câu hỏi hợp lý: làm thế nào để lấy một số ngẫu nhiên?

Trên thực tế, việc nhận được một số thực sự ngẫu nhiên khá khó thực hiện. Trên thực tế, khó đến mức các bộ đồng xử lý toán học đặc biệt được tích hợp vào một số máy tính để tạo ra các số đáp ứng tất cả các yêu cầu về tính ngẫu nhiên thực sự.

Các lập trình viên đã đưa ra giải pháp của riêng họ: số giả ngẫu nhiên . Số giả ngẫu nhiên là một loại dãy số mà các số có vẻ là ngẫu nhiên. Tuy nhiên, bằng cách thực hiện phân tích cẩn thận, một chuyên gia có thể tìm thấy các mẫu nhất định trong chuỗi. Những con số như vậy không phù hợp để mã hóa các tài liệu bí mật, nhưng chúng đủ để mô phỏng việc tung xúc xắc trong trò chơi.

Có nhiều thuật toán để tạo ra một dãy số giả ngẫu nhiên. Hầu như tất cả chúng đều tạo ra số ngẫu nhiên tiếp theo dựa trên số trước đó và một số số trợ giúp bổ sung.

Ví dụ: chương trình này sẽ hiển thị 1000các số không lặp lại:

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

Nhân tiện, chúng ta không nói về số giả ngẫu nhiên ở đây. Chúng ta đang nói về một dãy số giả ngẫu nhiên. Nhìn vào một con số, không thể biết đó là ngẫu nhiên hay không.

Thật vậy, có nhiều cách khác nhau để có được một số ngẫu nhiên:

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

2.Math.random()

Trong Java, Mathlớp có một phương thức đặc biệt trả về một số ngẫu nhiên. Và như bạn có thể đoán, phương pháp này được gọi là random. Nói chung, đây là cách gọi phương thức này:

Math.random()

Phương thức này không nhận tham số và trả về một số thực giả ngẫu nhiên trong phạm vi từ 0đến 1. Bản thân số 1 không được bao gồm trong phạm vi.

Ví dụ:

Mã số Đầu ra bảng điều khiển
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

Nhưng nếu phương pháp này không hoàn toàn là những gì bạn cần thì sao? Giả sử, bạn muốn viết một chương trình mô phỏng việc tung một con súc sắc sáu mặt. Làm cách nào để bạn nhận được các số nguyên ngẫu nhiên trong phạm vi 1..6, thay vì các số thực trong phạm vi 0..1?

Nó thực sự khá đơn giản.

Trước tiên, bạn cần ánh xạ phạm vi [0, 1)lên [0, 6). Để làm điều này, chỉ cần nhân kết quả trả về random()với 6. Tất nhiên, để lấy số nguyên, bạn cần làm tròn số:

Mã số Đầu ra bảng điều khiển
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

Trả getRandomDieNumber()về một số nguyên ngẫu nhiên trong phạm vi 0..5bao gồm. Nhưng nó sẽ không phải là một số trong tập hợp 1, 2, 3, 4, 5, 6. Nó sẽ là một số trong tập hợp 0, 1, 2, 3, 4, 5.

Nếu thứ bạn cần là các số trong tập hợp 1, 2, 3, 4, 5, 6, thì chỉ cần thêm một số vào các số ngẫu nhiên:

Mã số Đầu ra bảng điều khiển
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

Bây giờ điều đó thật hoàn hảo!



3. Randomlớp học

Java có một Randomlớp đặc biệt đóng gói một chuỗi các số giả ngẫu nhiên. Bạn có thể tạo một số đối tượng của Randomlớp. Mỗi đối tượng này sẽ tạo ra chuỗi số giả ngẫu nhiên của riêng nó.

Đây là một lớp siêu thú vị với rất nhiều phương pháp thú vị. Hãy bắt đầu với đơn giản nhất.

double nextDouble()

Phương thức này trả về một số thực ngẫu nhiên trong phạm vi 0.0- 1.0. Nó rất giống với Math.random()phương pháp. Và không có gì lạ, vì Math.random()phương thức chỉ đơn giản là gọi nextDouble()phương thức trên một Randomđối tượng.

float nextFloat()

Phương thức này rất giống với nextDouble()phương thức, nhưng số ngẫu nhiên được trả về là float. Nó cũng nằm trong phạm vi 0.0- 1.0. Và, như mọi khi trong Java, phạm vi không bao gồm 1.0chính số đó.

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

int nextInt(int max)

Phương thức này trả về một số nguyên ngẫu nhiên trong phạm vi [0, max). 0được bao gồm trong phạm vi, nhưng maxkhông phải là.

Nói cách khác, nếu bạn muốn lấy một số ngẫu nhiên trong tập hợp 1, 2, 3, 4, 5, 6, thì bạn cần thêm một số vào số ngẫu nhiên được trả về:

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

int nextInt()

Phương pháp này tương tự như phương pháp trước, nhưng nó không nhận bất kỳ tham số nào. Vì vậy, phạm vi cho các giá trị trả về của nó là gì? Từ -2 billionđến +2 billion.

Vâng, để được chính xác, từ -2147483648đến +2147483647.

long nextLong()

Phương pháp này tương tự như nextInt()phương pháp, nhưng giá trị trả về sẽ rơi vào một nơi nào đó trong toàn bộ phạm vi có thể có của longs.

boolean nextBoolean()

Phương thức này trả về một booleangiá trị ngẫu nhiên: falsehoặc true. Điều này rất thuận tiện khi bạn cần lấy một chuỗi dài các giá trị boolean ngẫu nhiên.

void nextBytes(byte[] data)

Phương thức này không trả về gì cả (vì kiểu trả về là void). Thay vào đó, nó lấp đầy mảng đã truyền với các giá trị ngẫu nhiên. Điều này rất tiện lợi khi bạn cần một bộ đệm lớn chứa đầy dữ liệu ngẫu nhiên.

double nextGaussian()

Phương thức này trả về một số thực ngẫu nhiên trong phạm vi 0.0- 1.0. Tuy nhiên, các con số không được phân bổ đều trong phạm vi này. Thay vào đó, chúng tuân theo phân phối chuẩn .

Các giá trị gần giữa phạm vi ( 0.5) sẽ xảy ra thường xuyên hơn các giá trị ở cuối phạm vi.

lớp ngẫu nhiên

Trong trường hợp của chúng tôi, đỉnh của phân phối giá trị sẽ ở0.5