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