JavaRush /Java Blogu /Random-AZ /Təcrübədə ehtimal nəzəriyyəsi və ya Random haqqında bilir...
Viacheslav
Səviyyə

Təcrübədə ehtimal nəzəriyyəsi və ya Random haqqında bilirsinizmi

Qrupda dərc edilmişdir
Təcrübədə ehtimal nəzəriyyəsi və ya Random haqqında bilirsinizmi - 1

Giriş

Dünyada ehtimal nəzəriyyəsini öyrənən çoxlu elmlər var. Elmlər isə müxtəlif bölmələrdən ibarətdir. Məsələn, riyaziyyatda təsadüfi hadisələrin, kəmiyyətlərin və s. öyrənilməsinə həsr olunmuş ayrıca bölmə var. Amma elmə yüngül yanaşmaq olmaz. Bu vəziyyətdə insanlar şans oyunları oynayarkən zər atmaqda hansı nümunələrin olduğunu anlamağa çalışdıqları zaman ehtimal nəzəriyyəsi formalaşmağa başladı. Diqqətlə baxsanız, ətrafımızda təsadüfi görünən çoxlu şeylər var. Ancaq təsadüfi hər şey tamamilə təsadüfi deyil. Ancaq bu barədə daha sonra. Java proqramlaşdırma dili də JDK-nın ilk versiyasından başlayaraq təsadüfi ədədləri dəstəkləyir. Java-da təsadüfi nömrələr java.util.Random sinifindən istifadə etməklə istifadə edilə bilər . Test üçün biz tutorialspoint java online kompilyatorundan istifadə edəcəyik . Rus dilində "zar" və ya kublar atmağı təqlid etmək üçün Random istifadə etməyin ibtidai bir nümunəsidir :
import java.util.Random;

public class HelloWorld{
    public static void main(String []args){
        Random rnd = new Random();
        int number = rnd.nextInt(6) + 1;
        System.out.println("Random number: " + number);
    }
}
Görünür ki, bu, Random təsvirinin sonu ola bilər , lakin bu o qədər də sadə deyil. Java API-də java.util.Random sinifinin təsvirini açaq . Və burada maraqlı şeylər görürük. Random sinfi psevdo-təsadüfi nömrələrdən istifadə edir. Necə? Belə çıxır ki, təsadüfi ədədlər o qədər də təsadüfi deyil?
Təcrübədə ehtimal nəzəriyyəsi və ya Random - 2 haqqında bilirsinizmi

Pseudo-təsadüfilik java.util.Random

Java.util.Random sinfi üçün sənədlərdə deyilir ki, Random nümunələri eyni toxum parametri ilə yaradılıbsa və nümunələr üzərində eyni hərəkət ardıcıllığı həyata keçirilirsə, onlar eyni nömrə ardıcıllığını qaytarır. Diqqətlə baxsaq görərik ki, Random əslində toxum kimi uzun dəyər alan konstruktora malikdir:
Random rnd1 = new Random(1L);
Random rnd2 = new Random(1L);
boolean test = rnd1.nextInt(6) == rnd2.nextInt(6);
System.out.println("Test: " + test);
Bu nümunə doğru olacaq, çünki hər iki nümunənin toxumu eynidir. Nə etməli? Standart konstruktor problemi qismən həll edir. Aşağıda Random konstruktorunun məzmununa bir nümunə verilmişdir :
public Random() {
	this(seedUniquifier() ^ System.nanoTime());
}
Defolt konstruktor bit üzrə eksklüziv OR əməliyyatından istifadə edir . Və bunun üçün cari vaxtı və bəzi toxumları təmsil edən uzun istifadə edir :
private static long seedUniquifier() {
	for (;;) {
		long current = seedUniquifier.get();
		long next = current * 181783497276652981L;
		if (seedUniquifier.compareAndSet(current, next))
			return next;
	}
}
Burada daha bir maraqlı cəhət ondan ibarətdir ki, seedUniquifier alıcı metoduna edilən hər bir çağırış seedUniquifier dəyərini dəyişir . Yəni, sinif təsadüfi ədədləri mümkün qədər səmərəli seçmək üçün nəzərdə tutulmuşdur. Bununla belə, sənədlərdə deyildiyi kimi, onlar " kriptoqrafik cəhətdən təhlükəsiz deyillər ". Yəni kriptoqrafik məqsədlər üçün istifadənin bəzi məqsədləri üçün (parolun yaradılması və s.) uyğun deyil, çünki düzgün yanaşma ilə ardıcıllıq proqnozlaşdırılır. İnternetdə bu mövzuda nümunələr var, məsələn, burada: “ Java-da növbəti Math.random()-un proqnozlaşdırılması ”. Və ya məsələn burada mənbə kodu: " Zəif Kripto Zəiflik ". java.util.Random (təsadüfi ədədlər generatoru) müəyyən bir “qısa yola” malikdir , yəni zəngin Math.random vasitəsilə yerinə yetirilən qısaldılmış versiyası:
public static void main(String []args){
	int random_number = 1 + (int) (Math.random() * 6);
	System.out.println("Value: " + random_number);
}
Ancaq diqqətlə baxsanız, içəridə eyni Random oturur:
public static double random() {
	return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
private static final class RandomNumberGeneratorHolder {
	static final Random randomNumberGenerator = new Random();
}
JavaDoc " kriptoqrafik cəhətdən təhlükəsiz psevdo-təsadüfi ədəd generatoru " üçün SecureRandom sinifindən istifadə etməyi məsləhət görür .
Təcrübədə ehtimal nəzəriyyəsi və ya Random haqqında bilirsinizmi - 3

Təhlükəsiz Random Java

SecureRandom sinfi java.util.Random alt sinfidir və java.security paketində yerləşir . Bu iki sinfin müqayisəsini " Java.util.Random və java.security.SecureRandom arasındakı fərq " məqaləsində oxumaq olar . Bu SecureRandom niyə bu qədər yaxşıdır? Fakt budur ki, onun üçün təsadüfi ədədlərin mənbəyi "əsas entropiya hovuzu" kimi sehrli bir şeydir. Bu həm müsbət, həm də mənfi cəhətdir. Bunun çatışmazlıqları haqqında məqalədə oxuya bilərsiniz: “ Java.security.SecureRandom təhlükələri ”. Bir sözlə, Linux-da nüvə təsadüfi nömrə generatoru (RNG) var. RNG, klaviatura və disk vaxtları, siçan hərəkətləri, fasilələr və şəbəkə trafiki kimi sistemdəki təsadüfi hadisələrə əsasən doldurulan entropiya hovuzundan verilənlər əsasında təsadüfi ədədlər yaradır. Entropiya hovuzu haqqında daha çox məlumat " Linux-da təsadüfi nömrələr (RNG) və ya /dev/random və /dev/urandom " necə "doldurulacağı " materialında təsvir edilmişdir . Windows sistemlərində sun.security.provider.SecureRandom-da həyata keçirilən SHA1PRNG istifadə olunur. Java-nın inkişafı ilə SecureRandom da dəyişdi, bu barədə tam şəkil üçün “ Aprel 2016-cı ilin Java SecureRandom yeniləmələri ” icmalında oxumağa dəyər.
Təcrübədə ehtimal nəzəriyyəsi və ya Random haqqında bilirsinizmi - 4

Multithreading və ya Sezar kimi olun

Random sinfinin koduna baxsanız , heç bir problemi göstərmir. Metodlar sinxronlaşdırılmayıb . Ancaq bir AMMA var: bir neçə mövzuda standart konstruktor ilə Random yaratarkən , biz onlar arasında eyni nümunə toxumunu paylaşacağıq ki , bunun vasitəsilə Random yaradılacaq . Həm də yeni təsadüfi nömrə qəbul edildikdə, nümunənin daxili AtomicLong da dəyişir . Bir tərəfdən, məntiqi baxımdan bunun heç bir qəbahəti yoxdur, çünki... AtomicLong istifadə olunur . Digər tərəfdən, məhsuldarlıq da daxil olmaqla, hər şey üçün pul ödəməlisiniz. Həm də bunun üçün. Buna görə də, hətta java.util.Random üçün rəsmi sənədlərdə belə deyilir: " java.util.Random nümunələri təhlükəsizdir. Bununla belə, eyni java.util.Random nümunəsinin mövzular arasında eyni vaxtda istifadəsi mübahisələrə və nəticədə zəif performansa səbəb ola bilər. Nəzərə alın. əvəzinə çox yivli dizaynlarda ThreadLocalRandom istifadə edir . Yəni, çox yivli proqramlarda bir neçə mövzudan Random istifadə edərkən, ThreadLocalRandom sinifindən istifadə etmək daha yaxşıdır . Onun istifadəsi adi Random -dan bir qədər fərqlidir :
public static void main(String []args){
	int rand = ThreadLocalRandom.current().nextInt(1,7);
	System.out.println("Value: " + rand);
}
Gördüyünüz kimi, bunun üçün toxum təyin etmirik . Bu nümunə Oracle-ın rəsmi təlimatında təsvir edilmişdir: Concurrent Random Numbers . Bu sinif haqqında daha çox icmalda oxuya bilərsiniz: " Java-da ThreadLocalRandom bələdçisi ".
Təcrübədə ehtimal nəzəriyyəsi və ya Random - 5 haqqında bilirsiniz

StreamAPI və Random

Java 8-in buraxılması ilə bir çox yeni funksiyalarımız var. O cümlədən Stream API. Və dəyişikliklər Təsadüfi dəyərlərin yaranmasına da təsir etdi . Məsələn, Random sinifində və ya kimi təsadüfi dəyərləri olan Axın əldə etməyə imkan verən yeni üsullar var . Misal üçün: intdoublelong
import java.util.Random;

public class HelloWorld{
    public static void main(String []args){
        new Random().ints(10, 1, 7).forEach(n -> System.out.println(n));
    }
}
Yeni SplittableRandom sinfi də var :
import java.util.SplittableRandom;

public class HelloWorld{
    public static void main(String []args){
        new SplittableRandom().ints(10, 1, 7).forEach(n -> System.out.println(n));
    }
}
SplittableRandom və digər siniflər arasındakı fərq haqqında daha ətraflı burada oxuya bilərsiniz: " Java-da təsadüfi ədədlər yaratmağın müxtəlif yolları ".

Nəticə

Məncə, nəticə çıxarmağa dəyər. İstifadə olunan siniflər üçün JavaDoc-u diqqətlə oxumalısınız. İlk baxışdan Random kimi sadə bir şeyin arxasında qəddar zarafat edə biləcək nüanslar var. #Viaçeslav
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION