JavaRush /Java blogi /Random-UZ /Amalda ehtimollar nazariyasi yoki siz Random haqida bilas...
Viacheslav
Daraja

Amalda ehtimollar nazariyasi yoki siz Random haqida bilasizmi

Guruhda nashr etilgan
Amalda ehtimollar nazariyasi yoki tasodifiy haqida bilasizmi - 1

Kirish

Dunyoda ehtimollar nazariyasini o'rganadigan ko'plab fanlar mavjud. Fanlar esa turli bo'limlardan iborat. Masalan, matematikada tasodifiy hodisalar, miqdorlar va boshqalarni o'rganishga bag'ishlangan alohida bo'lim mavjud. Ammo ilm-fanga beparvo qaralmaydi. Bunday holda, odamlar tasodifiy o'yinlarni o'ynashda zar otishda qanday naqshlar borligini tushunishga harakat qilganda, ehtimollik nazariyasi shakllana boshladi. Agar diqqat bilan qarasangiz, atrofimizda tasodifiy tuyuladigan ko'plab narsalar mavjud. Ammo tasodifiy hamma narsa butunlay tasodifiy emas. Ammo bu haqda keyinroq. Java dasturlash tili JDK ning birinchi versiyasidan boshlab tasodifiy raqamlarni ham qo'llab-quvvatlaydi. Java'da tasodifiy raqamlar java.util.Random klassi yordamida ishlatilishi mumkin . Sinov uchun biz tutorialspoint java onlayn kompilyatoridan foydalanamiz . Rus tilidagi “zar” yoki kublarni tashlashga taqlid qilish uchun Random-dan foydalanishning oddiy misoli :
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);
    }
}
Bu Tasodifiy tavsifining oxiri bo'lishi mumkin tuyulishi mumkin , ammo bu unchalik oddiy emas. Java API da java.util.Random sinfining tavsifini ochamiz . Va bu erda biz qiziqarli narsalarni ko'ramiz. Random klassi psevdo-tasodifiy raqamlardan foydalanadi. Qanaqasiga? Ma'lum bo'lishicha, tasodifiy raqamlar unchalik tasodifiy emasmi?
Amalda ehtimollar nazariyasi yoki siz Random - 2 haqida bilasizmi

Pseudo-tasodifiylik java.util.Random

Java.util.Random klassi hujjatlarida aytilishicha, agar Random misollari bir xil asosiy parametr bilan yaratilgan bo'lsa va misollarda bir xil harakatlar ketma-ketligi bajarilsa, ular bir xil raqamlar ketma-ketligini qaytaradi. Agar diqqat bilan qaraydigan bo'lsak, Random-da aslida urug' sifatida uzoq qiymatga ega bo'lgan konstruktor borligini ko'rishimiz mumkin :
Random rnd1 = new Random(1L);
Random rnd2 = new Random(1L);
boolean test = rnd1.nextInt(6) == rnd2.nextInt(6);
System.out.println("Test: " + test);
Bu misol haqiqatga qaytadi, chunki ikkala misolning urug'i bir xil. Nima qilsa bo'ladi? Standart konstruktor muammoni qisman hal qiladi. Quyida Random konstruktor mazmuniga misol keltirilgan :
public Random() {
	this(seedUniquifier() ^ System.nanoTime());
}
Standart konstruktor bit bo'yicha eksklyuziv OR operatsiyasidan foydalanadi . Va buning uchun joriy vaqtni ifodalovchi uzun va ba'zi urug'lardan foydalanadi :
private static long seedUniquifier() {
	for (;;) {
		long current = seedUniquifier.get();
		long next = current * 181783497276652981L;
		if (seedUniquifier.compareAndSet(current, next))
			return next;
	}
}
Bu erda yana bir qiziq narsa shundaki, seedUniquifier getter usuliga har bir qo'ng'iroq seedUniquifier qiymatini o'zgartiradi . Ya'ni, sinf tasodifiy sonlarni iloji boricha samarali tanlash uchun mo'ljallangan. Biroq, hujjatlarda aytilganidek, ular " kriptografik jihatdan xavfsiz emas ". Ya'ni, kriptografik maqsadlarda foydalanishning ba'zi maqsadlari uchun (parol yaratish va boshqalar) mos kelmaydi, chunki to'g'ri yondashuv bilan ketma-ketlik bashorat qilinadi. Internetda ushbu mavzu bo'yicha misollar mavjud, masalan, bu erda: “ Java-da keyingi Math.random() ni bashorat qilish ”. Yoki, masalan, manba kodi bu erda: " Zaiflik zaif kripto ". java.util.Random (tasodifiy raqamlar generatori) ma'lum bir "yorliq" ga ega , ya'ni Math.random orqali amalga oshiriladigan qo'ng'iroqning qisqartirilgan versiyasi:
public static void main(String []args){
	int random_number = 1 + (int) (Math.random() * 6);
	System.out.println("Value: " + random_number);
}
Ammo diqqat bilan qarasangiz, xuddi shu Random ichkarida o'tiradi:
public static double random() {
	return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
private static final class RandomNumberGeneratorHolder {
	static final Random randomNumberGenerator = new Random();
}
JavaDoc " kriptografik jihatdan xavfsiz psevdo-tasodifiy raqamlar generatori " uchun SecureRandom sinfidan foydalanishni maslahat beradi .
Amalda ehtimollar nazariyasi yoki siz Random - 3 haqida bilasizmi

Xavfsiz tasodifiy Java

SecureRandom klassi java.util.Random ning quyi sinfidir va java.security paketida joylashgan . Ushbu ikki sinfning taqqoslanishi " Java.util.Random va java.security.SecureRandom o'rtasidagi farq " maqolasida o'qilishi mumkin . Nima uchun bu SecureRandom juda yaxshi? Gap shundaki, uning uchun tasodifiy sonlar manbai "asosiy entropiya hovuzi" kabi sehrli narsadir. Bu ham ortiqcha, ham minus. Buning kamchiliklari haqida siz maqolada o'qishingiz mumkin: “ Java.security.SecureRandom xavflari ”. Qisqasi, Linux yadro tasodifiy sonlar generatoriga (RNG) ega. RNG tizimdagi tasodifiy hodisalar, masalan, klaviatura va disk vaqtlari, sichqonchaning harakati, uzilishlar va tarmoq trafigini hisobga olgan holda to'ldiriladigan entropiya hovuzidan olingan ma'lumotlar asosida tasodifiy sonlarni hosil qiladi. Entropiya hovuzi haqida ko'proq ma'lumot " Linuxdagi tasodifiy raqamlar (RNG) yoki /dev/random va /dev/urandom" "to'ldirish " bo'limida tasvirlangan . Windows tizimlarida sun.security.provider.SecureRandom da amalga oshirilgan SHA1PRNG ishlatiladi. Java rivojlanishi bilan SecureRandom ham o'zgardi, bu haqda to'liq rasm uchun " 2016 yil aprel holatiga ko'ra Java SecureRandom yangilanishlari " sharhida o'qish kerak.
Amalda ehtimollar nazariyasi yoki siz Random - 4 haqida bilasizmi

Multithreading yoki Qaysar kabi bo'ling

Random sinfining kodiga qarasangiz , hech narsa muammoni ko'rsatmaydi. Usullar sinxronlashtirilmagan deb belgilanmagan . Lekin bitta BUTUN bor: bir nechta iplardagi standart konstruktor bilan Random ni yaratishda biz ular o'rtasida bir xil namuna urug'ini baham ko'ramiz , bu orqali Random yaratiladi . Shuningdek, yangi tasodifiy raqam olinganda, misolning ichki AtomicLong ham o'zgaradi . Bir tomondan, mantiqiy nuqtai nazardan buning hech qanday yomon joyi yo'q, chunki... AtomicLong ishlatiladi . Boshqa tomondan, siz hamma narsa uchun, jumladan, hosildorlik uchun to'lashingiz kerak. Va buning uchun ham. Shuning uchun, hatto java.util.Random uchun rasmiy hujjatlarda shunday deyilgan: " Java.util.Random misollari ish zarrachalari xavfsizdir. Biroq, bir xil java.util.Random misolini mavzular bo'ylab bir vaqtda qo'llash tortishuvlarga va natijada yomon ishlashga olib kelishi mumkin. O'ylab ko'ring. Buning o'rniga ko'p tarmoqli dizaynlarda ThreadLocalRandom dan foydalanish ". Ya'ni, ko'p oqimli ilovalarda bir nechta iplardan Random- dan faol foydalanilganda, ThreadLocalRandom sinfidan foydalanish yaxshidir . Uning ishlatilishi oddiy Random dan biroz farq qiladi :
public static void main(String []args){
	int rand = ThreadLocalRandom.current().nextInt(1,7);
	System.out.println("Value: " + rand);
}
Ko'rib turganingizdek, biz buning uchun urug'ni belgilamaymiz . Ushbu misol Oracle rasmiy qo'llanmasida tasvirlangan: Bir vaqtning o'zida tasodifiy raqamlar . Ushbu sinf haqida ko'proq sharhda o'qishingiz mumkin: " Java-da ThreadLocalRandom qo'llanmasi ".
Amalda ehtimollar nazariyasi yoki siz Random - 5 haqida bilasizmi

StreamAPI va Random

Java 8-ning chiqarilishi bilan bizda ko'plab yangi xususiyatlar mavjud. Shu jumladan Stream API. Va o'zgarishlar Tasodifiy qiymatlarni yaratishga ham ta'sir qildi . Masalan, Random sinfida yoki kabi tasodifiy qiymatlarga ega Streamni olish imkonini beruvchi yangi usullar mavjud . Masalan: 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));
    }
}
Shuningdek, SplittableRandom yangi sinfi mavjud :
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 va boshqa sinflar o'rtasidagi farq haqida ko'proq ma'lumotni bu erda o'qishingiz mumkin: " Java'da tasodifiy raqamlarni yaratishning turli usullari ".

Xulosa

Menimcha, xulosa chiqarishga arziydi. Ishlatilgan sinflar uchun JavaDoc ni diqqat bilan o'qib chiqishingiz kerak. Tasodifiy kabi bir qarashda oddiy narsaning orqasida shafqatsiz hazil o'ynashi mumkin bo'lgan nuanslar mavjud. #Viacheslav
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION