Valószínűség Java-ban

1. Áttekintés

Ebben az oktatóanyagban megnézünk néhány példát arra, hogy miként valósíthatjuk meg a valószínűséget a Java-val.

2. Az alapvető valószínűség szimulálása

A Java valószínűségének szimulálásához első lépésként véletlenszámokat kell létrehoznunk. Szerencsére a Java rengeteg lehetőséget biztosít számunkra véletlenszám-generátorok.

Ebben az esetben a SplittableRandom osztály, mert kiváló minőségű véletlenszerűséget nyújt és viszonylag gyors:

SplittableRandom random = új SplittableRandom ();

Ezután elő kell állítanunk egy számot egy tartományban, és össze kell hasonlítanunk egy másik, az adott tartományból kiválasztott számmal. A tartomány minden számának egyenlő esélye van a sorsolásra. Amint ismerjük a tartományt, tudjuk a választott szám megrajzolásának valószínűségét. Így ellenőrizzük a valószínűséget:

logikai valószínűlegFalse = random.nextInt (10) == 0

Ebben a példában 0 és 9 közötti számokat húztunk. Ezért a 0 rajzolásának valószínűsége egyenlő 10% -kal. Most vegyünk egy véletlen számot, és teszteljük, hogy a kiválasztott szám alacsonyabb-e, mint a rajzolt:

logikai whoKnows = random.nextInt (1, 101) <= 50

Itt 1-től 100-ig húztunk számokat. Annak esélye, hogy véletlenszámunk kisebb vagy egyenlő legyen 50-vel, pontosan 50%.

3. Egységes elosztás

Az eddig generált értékek az egységes eloszlásba esnek. Ez azt jelenti minden esemény, például valamilyen szám dobása egy kockán, egyenlő eséllyel történik.

3.1. Funkció meghívása adott valószínűséggel

Tegyük fel, hogy időnként szeretnénk végrehajtani egy feladatot, és ellenőrizni annak valószínűségét. Például működtetünk egy e-kereskedelmi webhelyet, és kedvezményt szeretnénk adni felhasználóink ​​10% -ának.

Ehhez hajtsunk végre egy olyan módszert, amely három paramétert vesz fel: egy beszállítót, amelyre az esetek bizonyos százalékában hivatkozni fog, egy második szállítót, amelyre a többi esetben hivatkozni fog, és a valószínűséget.

Először kijelentjük SplittableRandom mint Lusta a Vavr segítségével. Így csak egyszer állíthatjuk be, első kérésre:

privát döntő Lazy random = Lusta.of (SplittableRandom :: new); 

Ezután megvalósítjuk a valószínűség-kezelő funkciót:

public withProbability (Beszállító pozitívCase, Szállító negatívCase, int valószínűség) {SplittableRandom random = this.random.get (); if (random.nextInt (1, 101) <= valószínűség) {return pozitívCase.get (); } else {return negativeCase.get (); }}

3.2. Mintavételi valószínűség Monte Carlo módszerrel

Fordítsuk meg az előző szakaszban látott folyamatot. Ehhez a valószínűséget Monte Carlo módszerrel mérjük meg. Nagy mennyiségű véletlenszerű eseményt generál, és megszámolja, hogy hányan teljesítik a megadott feltételt. Akkor hasznos, ha a valószínűséget nehéz vagy lehetetlen analitikusan kiszámítani.

Például, ha hatoldalas kockákat nézünk, tudjuk, hogy egy bizonyos szám dobásának valószínűsége 1/6. De, ha van egy titokzatos kockánk, ismeretlen számú oldallal, nehéz megmondani, mi lenne a valószínűsége. A kocka elemzése helyett csak annyiszor lehet dobni, hogy megszámoljuk, hányszor fordulnak elő bizonyos események.

Lássuk, hogyan tudjuk megvalósítani ezt a megközelítést. Először megpróbáljuk az 1-es számot milliószor 10% -os valószínűséggel előállítani, és megszámoljuk:

int numberOfSamples = 1_000_000; int valószínűség = 10; int howManyTimesInvoked = Stream.generate (() -> randomInvoker.withProbability (() -> 1, () -> 0, valószínűség)) .limit (numberOfSamples) .mapToInt (e -> e) .sum ();

Ezután a generált számok összege elosztva a minták számával az esemény valószínűségének közelítője lesz:

int monteCarloProbability = (howManyTimesInvoked * 100) / numberOfSamples; 

Ne feledje, hogy a kiszámított valószínűség hozzávetőleges. Minél nagyobb a minták száma, annál jobb lesz a közelítés.

4. Egyéb disztribúciók

Az egységes elosztás jól működik olyan dolgok modellezéséhez, mint a játékok. Ahhoz, hogy a játék igazságos legyen, az összes eseménynek gyakran azonos valószínűséggel kell történnie.

A való életben azonban az elosztások általában bonyolultabbak. Az esélyek nem egyenlőek arra, hogy különböző dolgok történjenek.

Például nagyon kevés rendkívül alacsony és nagyon kevés rendkívül magas ember van. A legtöbb ember átlagos magasságú, ami azt jelenti, hogy az emberek magassága a normális eloszlást követi. Ha véletlenszerű emberi magasságokat kell létrehoznunk, akkor nem lesz elegendő véletlenszerű számú láb generálása.

Szerencsére nem kell magunknak megvalósítanunk az alapul szolgáló matematikai modellt. Tudnunk kell, melyik disztribúciót kell használni és hogyan kell konfigurálnipéldául statisztikai adatok felhasználásával.

Az Apache Commons könyvtár számos disztribúció megvalósítását biztosítja számunkra. Vezessük be vele a normál eloszlást:

privát statikus végső dupla MEAN_HEIGHT = 176,02; privát statikus végső kettős STANDARD_DEVIATION = 7.11; privát statikus NormalDistribution disztribúció = új NormalDistribution (MEAN_HEIGHT, STANDARD_DEVIATION); 

Ennek az API-nak a használata nagyon egyszerű - a minta módszer véletlen számot von le az eloszlásból:

nyilvános statikus kettős generálásNormalHeight () {return distribution.sample (); }

Végül fordítsuk meg a folyamatot:

nyilvános statikus kettős valószínűségOfHeightBetween (dupla magasságLowerExclusive, dupla magasságUpperInclusive) {visszatérési elosztás.probability (heightLowerExclusive, heightUpperInclusive); }

Ennek eredményeként megkapjuk annak valószínűségét, hogy egy személy magassága két határ között legyen. Ebben az esetben az alsó és a felső magasság.

5. Következtetés

Ebben a cikkben megtanultuk, hogyan lehet véletlenszerű eseményeket generálni, és hogyan lehet kiszámítani azok bekövetkezésének valószínűségét. A különböző helyzetek modellezéséhez egységes és normális eloszlást használtunk.

A teljes példa a GitHub oldalon található.