Waarschijnlijkheid in Java

1. Overzicht

In deze tutorial zullen we enkele voorbeelden bekijken van hoe we waarschijnlijkheid kunnen implementeren met Java.

2. Simuleren van basiskans

Om waarschijnlijkheid in Java te simuleren, moeten we eerst willekeurige getallen genereren. Gelukkig biedt Java ons genoeg willekeurige getallengeneratoren.

In dit geval gebruiken we de SplittableRandom class omdat het willekeurigheid van hoge kwaliteit biedt en relatief snel is:

SplittableRandom random = nieuwe SplittableRandom ();

Vervolgens moeten we een nummer in een bereik genereren en dit vergelijken met een ander nummer dat uit dat bereik is gekozen. Elk nummer in de reeks heeft een gelijke kans om getrokken te worden. Omdat we het bereik kennen, kennen we de kans dat het door ons gekozen nummer wordt getrokken. Op die manier beheersen we de waarschijnlijkheid:

boolean waarschijnlijkFalse = random.nextInt (10) == 0

In dit voorbeeld hebben we getallen van 0 tot 9 getekend. Daarom is de kans om 0 te tekenen gelijk aan 10%. Laten we nu een willekeurig getal nemen en testen of het gekozen getal lager is dan het getrokken getal:

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

Hier hebben we getallen van 1 tot 100 getrokken. De kans dat ons willekeurige getal kleiner of gelijk is aan 50 is precies 50%.

3. Uniforme distributie

Waarden die tot nu toe zijn gegenereerd, vallen in de uniforme verdeling. Dit betekent dat elke gebeurtenis, bijvoorbeeld het gooien van een nummer op een dobbelsteen, heeft een gelijke kans om te gebeuren.

3.1. Een functie oproepen met een bepaalde waarschijnlijkheid

Laten we nu zeggen dat we van tijd tot tijd een taak willen uitvoeren en de waarschijnlijkheid ervan willen beheersen. We exploiteren bijvoorbeeld een e-commercesite en we willen 10% van onze gebruikers korting geven.

Laten we hiervoor een methode implementeren die drie parameters gebruikt: een leverancier om in een bepaald percentage van de gevallen een beroep te doen, een tweede leverancier om in de rest van de gevallen een beroep te doen, en de waarschijnlijkheid.

Ten eerste verklaren we onze SplittableRandom net zo Lui met behulp van Vavr. Op deze manier instantiëren we het slechts één keer, op een eerste verzoek:

privé finale Lazy random = Lazy.of (SplittableRandom :: new); 

Vervolgens implementeren we de kansbeheerfunctie:

public withProbability (Supplier positiveCase, Supplier negativeCase, int probability) {SplittableRandom random = this.random.get (); if (random.nextInt (1, 101) <= kans) {return positiveCase.get (); } else {retourneer negativeCase.get (); }}

3.2. Bemonsteringskans met de Monte Carlo-methode

Laten we het proces omkeren dat we in de vorige sectie hebben gezien. Om dit te doen, meten we de kans met behulp van de Monte Carlo-methode. Het genereert een groot aantal willekeurige gebeurtenissen en telt hoeveel daarvan voldoen aan de gestelde voorwaarde. Het is handig als de kans moeilijk of onmogelijk analytisch te berekenen is.

Als we bijvoorbeeld kijken naar zeszijdige dobbelstenen, weten we dat de kans dat een bepaald getal wordt gegooid 1/6 is. Maar als we een mysterieuze dobbelsteen hebben met een onbekend aantal zijden, is het moeilijk te zeggen wat de kans is. In plaats van de dobbelstenen te analyseren, kunnen we deze gewoon meerdere keren gooien en tellen hoe vaak bepaalde gebeurtenissen plaatsvinden.

Laten we eens kijken hoe we deze aanpak kunnen implementeren. Eerst proberen we het nummer 1 te genereren met een kans van 10% voor een miljoen keer en ze te tellen:

int numberOfSamples = 1_000_000; int waarschijnlijkheid = 10; int howManyTimesInvoked = Stream.generate (() -> randomInvoker.withProbability (() -> 1, () -> 0, waarschijnlijkheid)) .limit (numberOfSamples) .mapToInt (e -> e) .sum ();

Vervolgens zal de som van de gegenereerde getallen gedeeld door het aantal monsters een benadering zijn van de waarschijnlijkheid van de gebeurtenis:

int monteCarloProbability = (howManyTimesInvoked * 100) / numberOfSamples; 

Houd er rekening mee dat de berekende kans wordt benaderd. Hoe hoger het aantal samples, hoe beter de benadering zal zijn.

4. Andere uitkeringen

De uniforme distributie werkt goed voor het modelleren van zaken als games. Om het spel eerlijk te laten zijn, moeten alle gebeurtenissen vaak dezelfde kans hebben dat ze plaatsvinden.

In het echte leven zijn distributies echter meestal gecompliceerder. De kansen zijn niet gelijk dat er verschillende dingen gebeuren.

Er zijn bijvoorbeeld maar heel weinig extreem kleine mensen en heel weinig extreem lange mensen. De meeste mensen zijn van gemiddelde lengte, wat betekent dat de lengte van mensen de normale verdeling volgt. Als we willekeurige menselijke hoogten moeten genereren, is het niet voldoende om een ​​willekeurig aantal voet te genereren.

Gelukkig hoeven we het onderliggende wiskundige model niet zelf te implementeren. We moeten weten welke distributie we moeten gebruiken en hoe we deze moeten configureren, bijvoorbeeld met behulp van statistische gegevens.

De Apache Commons-bibliotheek biedt ons implementaties voor verschillende distributies. Laten we de normale distributie ermee implementeren:

privé statische laatste dubbele MEAN_HEIGHT = 176.02; privé statische laatste dubbele STANDARD_DEVIATION = 7.11; privé statische NormalDistribution-distributie = nieuwe NormalDistribution (MEAN_HEIGHT, STANDARD_DEVIATION); 

Het gebruik van deze API is heel eenvoudig - de voorbeeldmethode haalt een willekeurig getal uit de distributie:

openbare statische dubbele genererenNormalHeight () {retour distributie.sample (); }

Laten we tot slot het proces omdraaien:

openbare statische dubbele probabilityOfHeightBetween (double heightLowerExclusive, double heightUpperInclusive) {return distribution.probability (heightLowerExclusive, heightUpperInclusive); }

Als resultaat krijgen we de kans dat een persoon een lengte heeft tussen twee grenzen. In dit geval de onderste en bovenste hoogte.

5. Conclusie

In dit artikel hebben we geleerd hoe we willekeurige gebeurtenissen kunnen genereren en hoe we de kans kunnen berekenen dat ze plaatsvinden. We gebruikten uniforme en normale distributies om verschillende situaties te modelleren.

Het volledige voorbeeld is te vinden op GitHub.