JavaRush /جاوا بلاگ /Random-UR /امکانی نظریہ عملی طور پر یا کیا آپ رینڈم کے بارے میں جانت...
Viacheslav
سطح

امکانی نظریہ عملی طور پر یا کیا آپ رینڈم کے بارے میں جانتے ہیں؟

گروپ میں شائع ہوا۔
Теория вероятностей на практике or знаете ли вы о Random - 1

تعارف

دنیا میں بہت سے سائنس ایسے ہیں جو نظریہ امکان کا مطالعہ کرتے ہیں۔ اور علوم مختلف حصوں پر مشتمل ہیں۔ مثال کے طور پر، ریاضی میں ایک الگ سیکشن ہے جو بے ترتیب واقعات، مقدار وغیرہ کے مطالعہ کے لیے مختص ہے۔ لیکن سائنس کو ہلکے سے نہیں لیا جاتا۔ اس معاملے میں، امکان کا نظریہ اس وقت شکل اختیار کرنا شروع ہوا جب لوگوں نے یہ سمجھنے کی کوشش کی کہ موقع کا کھیل کھیلتے ہوئے ڈائس پھینکنے میں کیا نمونے ہیں۔ اگر آپ قریب سے دیکھیں تو ہمارے اردگرد بہت سی بظاہر بے ترتیب چیزیں نظر آتی ہیں۔ لیکن بے ترتیب ہر چیز مکمل طور پر بے ترتیب نہیں ہے۔ لیکن بعد میں اس پر مزید۔ جاوا پروگرامنگ لینگویج میں JDK کے پہلے ورژن سے شروع ہونے والے بے ترتیب نمبروں کے لیے بھی حمایت حاصل ہے۔ جاوا میں بے ترتیب نمبروں کو java.util.Random کلاس کا استعمال کرتے ہوئے استعمال کیا جا سکتا ہے ۔ جانچ کے لیے، ہم tutorialspoint java online compiler استعمال کریں گے ۔ یہاں روسی میں "نرد" یا کیوبز پھینکنے کی تقلید کے لیے رینڈم کا استعمال کرنے کی ایک قدیم مثال ہے :
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);
    }
}
ایسا لگتا ہے کہ یہ Random کی تفصیل کا اختتام ہوسکتا ہے ، لیکن یہ اتنا آسان نہیں ہے۔ آئیے جاوا API میں java.util.Random کلاس کی تفصیل کھولتے ہیں۔ اور یہاں ہم دلچسپ چیزیں دیکھتے ہیں۔ رینڈم کلاس سیوڈو بے ترتیب نمبر استعمال کرتی ہے۔ وہ کیسے؟ یہ پتہ چلتا ہے کہ بے ترتیب نمبر اتنے بے ترتیب نہیں ہیں؟
Теория вероятностей на практике or знаете ли вы о Random - 2

چھدم بے ترتیب پن java.util.Random

java.util.Random کلاس کے لیے دستاویزات میں کہا گیا ہے کہ اگر رینڈم کی مثالیں ایک ہی سیڈ پیرامیٹر کے ساتھ تخلیق کی جاتی ہیں اور مثالوں پر ایک ہی سلسلے کی کارروائیاں انجام دی جاتی ہیں، تو وہ اعداد کی ایک جیسی ترتیب واپس کرتے ہیں۔ اور اگر ہم قریب سے دیکھیں تو ہم دیکھ سکتے ہیں کہ رینڈم میں دراصل ایک کنسٹرکٹر ہے جو بیج کے طور پر کچھ لمبی قیمت لیتا ہے:
Random rnd1 = new Random(1L);
Random rnd2 = new Random(1L);
boolean test = rnd1.nextInt(6) == rnd2.nextInt(6);
System.out.println("Test: " + test);
یہ مثال درست ہو جائے گی کیونکہ دونوں صورتوں کا بیج ایک ہی ہے۔ کیا کرنا ہے؟ ڈیفالٹ کنسٹرکٹر جزوی طور پر مسئلہ حل کرتا ہے۔ ذیل میں رینڈم کنسٹرکٹر کے مشمولات کی ایک مثال ہے ۔
public Random() {
	this(seedUniquifier() ^ System.nanoTime());
}
ڈیفالٹ کنسٹرکٹر bitwise exclusive OR آپریشن استعمال کرتا ہے ۔ اور موجودہ وقت کی نمائندگی کرنے والا ایک طویل اور اس کے لیے کچھ بیج استعمال کرتا ہے :
private static long seedUniquifier() {
	for (;;) {
		long current = seedUniquifier.get();
		long next = current * 181783497276652981L;
		if (seedUniquifier.compareAndSet(current, next))
			return next;
	}
}
Здесь интересно ещё и то, что каждый вызов метода получения seedUniquifier изменяет meaning seedUniquifier. То есть класс спроектирован так, чтобы максимально эффективно подбирать случайные числа. Однако, How и сказано в documentации, они "are not cryptographically secure". То есть для Howих-то целей использования в криптографических целей (генерация паролей и т.п.) не годится, т.к. последовательность при должном подходе предсказывается. На эту тему есть в интернете примеры, например тут: "Predicting the next Math.random() in Java". Или например исходный code тут: "Vulnerability Weak Crypto". У java.util.Random (генератора случайных чисел) есть некий "шорткат", то есть укороченная version вызова, которая выполняется через Math.random:
public static void main(String []args){
	int random_number = 1 + (int) (Math.random() * 6);
	System.out.println("Value: " + random_number);
}
Но если посмотреть внимательно, внутри сидит всё тот же Random:
public static double random() {
	return RandomNumberGeneratorHolder.randomNumberGenerator.nextDouble();
}
private static final class RandomNumberGeneratorHolder {
	static final Random randomNumberGenerator = new Random();
}
В JavaDoc советуют использовать класс SecureRandom для "cryptographically secure pseudo-random number generator".
Теория вероятностей на практике or знаете ли вы о Random - 3

Безопасный Random Java

Класс SecureRandom является наследником java.util.Random и расположен в пакете java.security. Сравнение этих двух классов можно прочитать в статье "Difference between java.util.Random and java.security.SecureRandom". Чем же так хорош этот SecureRandom? Дело в том, что для него источником случайных чисел является такая магически звучащая штука How "пул энтропии ядра". Это одновременно и плюс, и минус. Про минус этого можно прочитать в статье: "The dangers of java.security.SecureRandom". Если кратко, в Linux есть генератор случайных чисел ядра (RNG). RNG генерирует случайные числа на основе данных из пула энтропии (entropy pool), который наполняется на основе случайных событий в системе, таких How тайминги клавиатуры и дисков, движения мыши, прерывания (interrupts), сетевой трафик. Подробнее про пул энтропии изложено в материале "Случайные числа в Linux(RNG) or How «наполнить» /dev/random и /dev/urandom". На Windows системах используется SHA1PRNG, реализованная в sun.security.provider.SecureRandom. С развитием Java менялся и SecureRandom, о чём для полной картины стоит прочитать в обзоре "Java SecureRandom updates as of April 2016".
Теория вероятностей на практике or знаете ли вы о Random - 4

Многопоточность or будь How Цезарь

Если смотреть code класса Random, то вроде ничто не предвещает беды. Методы не помечены How synchronized. Но есть одно НО: при создании Random конструктором по умолчанию в нескольких потоках мы будем между ними делить один и тот же instance seed, по которому будет создаваться Random. А также при получении нового случайного числа у instance так же меняется внутренний AtomicLong. С одной стороны, в этом нет ничего страшного с логической точки зрения, т.к. используется AtomicLong. С другой стороны, за всё надо платить, в том числе производительностью. И за это тоже. Поэтому даже в официальной documentации к java.util.Random сказано: "Instances of java.util.Random are threadsafe. However, the concurrent use of the same java.util.Random instance across threads may encounter contention and consequent poor performance. Consider instead using ThreadLocalRandom in multithreaded designs". То есть в многопоточных applicationsх при активном использовании Random из нескольких потоков лучше использовать класс ThreadLocalRandom. Его использование немного отличается от обычного Random:
public static void main(String []args){
	int rand = ThreadLocalRandom.current().nextInt(1,7);
	System.out.println("Value: " + rand);
}
Как видим, для него мы не указываем seed. Данный пример описан в официальном tutorial от Oracle: Concurrent Random Numbers. Подробнее про данный класс можно прочитать в обзоре: "Guide to ThreadLocalRandom in Java".
Теория вероятностей на практике or знаете ли вы о Random - 5

StreamAPI и Random

Благодаря выходу Java 8 у нас появилось много новых возможностей. В том числе и Stream API. И изменения коснулись и генерации Random значений. Например, в классе Random появorсь новые методы, которые позволяют получить Stream со случайными значениями типа int, double or long. Например:
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));
    }
}
Также появился новый класс SplittableRandom:
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 от остальных классов можно прочитать здесь: "Different ways to create Random numbers in Java".

Заключение

Думаю, стоит сделать вывод. Нужно внимательно читать JavaDoc к используемым классам. За такой простой на первый взгляд вещью How Random стоят нюансы, которые могут сыграть злую шутку. #Viacheslav
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION