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

하지만 이 방법이 필요한 것이 아니라면 어떻게 해야 할까요? 육면체 주사위 굴리기를 시뮬레이트하는 프로그램을 작성하고 싶다고 가정해 보겠습니다. 0..1 범위의 실수 대신 1..6 범위의 임의의 정수를 어떻게 얻습니까?

실제로 매우 간단합니다.

[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.

필요한 것이 집합의 숫자인 경우 1, 2, 3, 4, 5, 6임의의 숫자에 1을 추가하면 됩니다.

암호 콘솔 출력
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클래스

RandomJava 에는 의사 난수 시퀀스를 캡슐화하는 특수 클래스가 있습니다 . 클래스 의 여러 개체를 만들 수 있습니다 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않습니다.

즉, 집합에서 난수를 얻으려면 1, 2, 3, 4, 5, 6반환된 난수에 1을 추가해야 합니다.

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

int nextInt()

이 방법은 이전 방법과 유사하지만 매개변수를 사용하지 않습니다. 반환 값의 범위는 무엇입니까? 에서 -2 billion까지 +2 billion.

음, 정확히 말하면 에서 -2147483648까지입니다 +2147483647.

long nextLong()

이 메서드는 메서드와 유사 nextInt()하지만 반환 값은 s의 가능한 전체 범위 내 어딘가에 속합니다 long.

boolean nextBoolean()

이 메서드는 임의의 boolean값을 반환합니다: false또는 true. 이는 무작위 부울 값의 긴 시퀀스를 가져와야 할 때 매우 편리합니다.

void nextBytes(byte[] data)

이 메서드는 아무것도 반환하지 않습니다(반환 유형이 이므로 void). 대신 전달된 배열을 임의의 값으로 채웁니다. 이는 임의의 데이터로 채워진 큰 버퍼가 필요할 때 매우 편리합니다.

double nextGaussian()

0.0이 메서드는 - 범위의 임의의 실수를 반환합니다 1.0. 그러나 숫자는 이 범위에서 고르게 분포되지 않습니다. 대신 정규 분포를 따릅니다 .

범위 중간에 가까운 값( 0.5)은 범위 끝에 있는 값보다 더 자주 발생합니다.

랜덤 클래스

우리의 경우 가치 분포의 정점은0.5