1. Pseudorandom na mga numero

Minsan ang isang programmer ay nahaharap sa tila simpleng mga gawain: "pumili ng random na pelikula mula sa isang partikular na listahan", "pumili ng nanalo sa lottery", "shuffle ang playlist kapag inalog ng user ang kanyang smartphone", "pumili ng random na numero para i-encrypt ang isang mensahe" , atbp. Sa bawat kaso, nagtatanong ang developer ng lohikal na tanong: paano makakuha ng random na numero?

Sa totoo lang, ang pagkuha ng tunay na random na numero ay medyo mahirap gawin. Sa katunayan, napakahirap na ang mga espesyal na mathematical coprocessor ay binuo sa ilang mga computer upang makabuo ng mga numero na nakakatugon sa lahat ng mga kinakailangan para sa tunay na randomness.

Ang mga programmer ay gumawa ng sarili nilang solusyon: mga pseudorandom na numero . Ang mga pseudorandom na numero ay isang uri ng pagkakasunud-sunod, na ang mga numero ay tila random. Gayunpaman, sa pamamagitan ng pagsasagawa ng maingat na pagsusuri, makakahanap ang isang eksperto ng ilang partikular na pattern sa pagkakasunud-sunod. Ang mga naturang numero ay hindi angkop para sa pag-encrypt ng mga lihim na dokumento, ngunit sapat na ang mga ito para gayahin ang roll ng isang die sa isang laro.

Mayroong maraming mga algorithm para sa pagbuo ng isang pagkakasunud-sunod ng mga pseudorandom na numero. Halos lahat sa kanila ay bumubuo ng susunod na random na numero batay sa nakaraang numero at ilang karagdagang numero ng katulong.

Halimbawa, ang program na ito ay magpapakita ng 1000mga hindi umuulit na numero:

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

Sa pamamagitan ng paraan, hindi namin pinag-uusapan ang mga pseudorandom na numero dito. Pinag-uusapan natin ang tungkol sa pagkakasunod-sunod ng mga pseudorandom na numero. Sa pagtingin sa isang solong numero, imposibleng sabihin kung ito ay random o hindi.

Sa katunayan, may iba't ibang paraan para makakuha ng random na numero:

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

2.Math.random()

Sa Java, ang Mathklase ay may espesyal na paraan na nagbabalik ng random na numero. At tulad ng maaari mong hulaan, ang pamamaraan ay tinatawag na random. Sa pangkalahatan, narito ang hitsura ng pagtawag sa paraang ito:

Math.random()

Ang pamamaraang ito ay walang mga parameter at nagbabalik ng pseudorandom na tunay na numero sa hanay mula 0hanggang 1. Ang numero 1 mismo ay hindi kasama sa hanay.

Halimbawa:

Code Output ng console
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

Ngunit paano kung ang pamamaraang ito ay hindi kung ano ang kailangan mo? Ipagpalagay, gusto mong magsulat ng isang programa na gayahin ang pag-roll ng isang anim na panig na mamatay. Paano ka makakakuha ng mga random na integer sa hanay na 1..6, sa halip na mga tunay na numero sa hanay na 0..1?

Ito ay talagang medyo simple.

Una, kailangan mong imapa ang hanay [0, 1)sa [0, 6). Upang gawin ito, i-multiply lang ang resulta na ibinalik random()ng 6. Siyempre, upang makakuha ng mga integer, kailangan mong i-round up:

Code Output ng console
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

Nagbabalik ang getRandomDieNumber()isang random na integer sa saklaw 0..5na kasama. Ngunit hindi ito magiging isang numero sa set 1, 2, 3, 4, 5, 6. Ito ay magiging isang numero sa set 0, 1, 2, 3, 4, 5.

Kung ang kailangan mo ay mga numero sa set 1, 2, 3, 4, 5, 6, magdagdag lang ng isa sa mga random na numero:

Code Output ng console
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

Ngayon ay perpekto na!



3. Randomklase

Ang Java ay may espesyal Randomna klase na sumasaklaw sa isang sequence ng mga pseudorandom na numero. Maaari kang lumikha ng ilang mga bagay ng Randomklase. Ang bawat isa sa mga bagay na ito ay bubuo ng sarili nitong sequence ng mga pseudorandom na numero.

Ito ay isang sobrang kawili-wiling klase na may maraming kawili-wiling pamamaraan. Magsimula tayo sa pinakasimpleng.

double nextDouble()

Ang pamamaraang ito ay nagbabalik ng random na tunay na numero sa hanay 0.0- 1.0. Ito ay halos kapareho sa Math.random()pamamaraan. At hindi nakakagulat, dahil ang Math.random()pamamaraan ay tinatawag lamang ang nextDouble()pamamaraan sa isang Randombagay.

float nextFloat()

Ang pamamaraang ito ay halos kapareho sa nextDouble()pamamaraan, ngunit ang ibinalik na random na numero ay isang float. Ito rin ay namamalagi sa hanay 0.0- 1.0. At, gaya ng nakasanayan sa Java, hindi kasama sa range ang numero 1.0mismo.

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

int nextInt(int max)

Ang pamamaraang ito ay nagbabalik ng random na integer sa hanay [0, max). 0ay kasama sa hanay, ngunit maxhindi.

Sa madaling salita, kung gusto mong makakuha ng random na numero sa set 1, 2, 3, 4, 5, 6, kailangan mong magdagdag ng isa sa ibinalik na random na numero:

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

int nextInt()

Ang pamamaraang ito ay katulad ng nauna, ngunit hindi ito kumukuha ng anumang mga parameter. Kaya ano ang saklaw para sa mga halaga ng pagbabalik nito? Mula -2 billionsa +2 billion.

Well, upang maging tumpak, mula -2147483648sa +2147483647.

long nextLong()

Ang pamamaraang ito ay katulad ng nextInt()pamamaraan, ngunit ang halaga ng pagbabalik ay mahuhulog sa isang lugar sa buong posibleng hanay ng longs.

boolean nextBoolean()

Ang pamamaraang ito ay nagbabalik ng random booleanna halaga: falseo true. Ito ay napaka-maginhawa kapag kailangan mong makakuha ng mahabang pagkakasunud-sunod ng mga random na halaga ng boolean.

void nextBytes(byte[] data)

Ang pamamaraang ito ay walang ibinabalik (dahil ang uri ng pagbabalik ay void). Sa halip, pinupuno nito ang naipasa na array ng mga random na halaga. Ito ay napakadaling gamitin kapag kailangan mo ng malaking buffer na puno ng random na data.

double nextGaussian()

Ang pamamaraang ito ay nagbabalik ng random na tunay na numero sa hanay 0.0- 1.0. Gayunpaman, ang mga numero ay hindi pantay na ipinamamahagi sa hanay na ito. Sa halip, sinusunod nila ang isang normal na pamamahagi .

Ang mga value na malapit sa gitna ng range ( 0.5) ay magaganap nang mas madalas kaysa sa mga value sa dulo ng range.

Random na klase

Sa aming kaso, ang rurok ng pamamahagi ng halaga ay nasa0.5