1.偽隨機數

有時,程序員面臨看似簡單的任務:“從特定列表中隨機選擇一部電影”、“選擇彩票中獎者”、“當用戶搖動他或她的智能手機時隨機播放播放列表”、“選擇一個隨機數來加密消息”等等。在每種情況下,開發人員都會提出一個合乎邏輯的問題:如何獲得隨機數?

實際上,獲得一個真正的隨機數是相當困難的。事實上,在某些計算機中內置特殊的數學協處理器以生成滿足真正隨機性的所有要求的數字是如此困難。

程序員想出了他們自己的解決方案:偽隨機數。偽隨機數是一種序列,其數字看起來是隨機的。然而,通過仔細分析,專家可以找到序列中的某些模式。這些數字不適合加密機密文件,但足以模擬遊戲中的擲骰子。

有許多算法可以生成偽隨機數序列。幾乎所有這些都根據前一個數字和一些額外的輔助數字生成下一個隨機數。

例如,這個程序將顯示1000不重複的數字:

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

順便說一下,我們這裡不是在談論偽隨機數。我們談論的是一系列偽隨機數。單單看一個數字,是無法判斷是不是隨機的。

實際上,有多種方法可以獲取隨機數:

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

2.Math.random()

在 Java 中,該類Math有一個返回隨機數的特殊方法。正如您可能猜到的那樣,該方法稱為random. 通常,調用此方法的方式如下:

Math.random()

此方法不接受任何參數,並返回範圍從0到 的偽隨機實數1。數字 1 本身不包含在範圍內。

例子:

代碼 控制台輸出
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

但是,如果這種方法不是您所需要的呢?假設,您想編寫一個程序來模擬擲六面骰子。如何獲得 1..6 範圍內的隨機整數,而不是 0..1 範圍內的實數?

其實很簡單。

首先,您需要將範圍映射[0, 1)[0, 6). 為此,只需將 返回的結果乘以random()即可6。當然,要得到整數,你需要四捨五入:

代碼 控制台輸出
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

返回getRandomDieNumber()範圍內的隨機整數0..5。但它不會是集合中的數字1, 2, 3, 4, 5, 6。它將是集合中的一個數字0, 1, 2, 3, 4, 5

如果您需要的是 set 中的數字1, 2, 3, 4, 5, 6,則只需將隨機數加一即可:

代碼 控制台輸出
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

現在太完美了!



3.Random

Java 有一個特殊的Random類,它封裝了一系列偽隨機數。您可以創建該類的多個對象Random。這些對像中的每一個都會生成自己的偽隨機數序列。

這是一個超級有趣的類,有很多有趣的方法。讓我們從最簡單的開始。

double nextDouble()

此方法返回範圍0.0-中的隨機實數1.0。它與Math.random()方法非常相似。難怪,因為該Math.random()方法只是調用對像nextDouble()上的方法Random

float nextFloat()

這個方法和方法很相似nextDouble(),但是返回的隨機數是一個float. 它也位於範圍0.0- 1.0。而且,與在 Java 中一樣,範圍不包括數字1.0本身。

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

int nextInt(int max)

此方法返回範圍內的隨機整數[0, max)0包含在範圍內,但max不是。

換句話說,如果你想得到 set 中的一個隨機數1, 2, 3, 4, 5, 6,那麼你需要在返回的隨機數上加一:

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

int nextInt()

此方法與上一個方法類似,但它不帶任何參數。那麼它的返回值範圍是多少呢?從-2 billion+2 billion

好吧,準確地說,從-2147483648+2147483647

long nextLong()

這個方法和方法類似nextInt(),但是返回值會落在longs的整個可能範圍內的某處。

boolean nextBoolean()

此方法返回一個隨機boolean值:falsetrue。當您需要獲取一長串隨機布爾值時,這非常方便。

void nextBytes(byte[] data)

此方法不返回任何內容(因為返回類型是void)。相反,它用隨機值填充傳遞的數組。當您需要一個充滿隨機數據的大緩衝區時,這非常方便。

double nextGaussian()

此方法返回範圍0.0-中的隨機實數1.0。但是,數字在這個範圍內分佈不均。相反,它們服從正態分佈

接近範圍中間 ( 0.5) 的值比範圍末端的值出現的頻率更高。

隨機類

在我們的例子中,價值分佈的峰值將在0.5