# java.util.Random - Zwei Zahlen mit festgesetzter Wahrscheinlichkeit?



## NeX (17. Feb 2016)

Hallo zusammen!
Ich sitze jetzt schon ewig an dieser Aufgabe und finde einfach keinen richtigen Zugang. Ich soll eine Methode schreiben, die eine von zwei Zahlen (10 und 20) mit einer Wahrscheinlichkeit von 10% (für die 10) und 90% (für die 20) zurückgibt. 

Ich weiß, wie ich Zahlen in einem Raum von 10 BIS 20 erstellen könnte oder wie es funktionieren würde, wenn die beiden direkt hintereinander liegen würden, aber so bin ich grad total überfordert, besonders von der Wahrscheinlichkeit.

Könntet ihr mir vielleicht einen Tipp geben?

Liebe Grüße
NeX


----------



## Blender3D (17. Feb 2016)

Mache Zufallszahlen von 1 - 10.
1, 2 --> 10
3-10 --> 20


----------



## Jardcore (17. Feb 2016)

Du kannst dir ein zufälligen Wert durch Math.random() geben lassen.
Dieser Wert liegt zwischen 0 und 1.
Der Wert kann nun zu einer Wahrscheinlichkeit von 10% unter 0.1 liegen und zu 90% über 0.1. 
Die 0 spiegelt dabei 0% wieder und die 1 die 100%.
Daraus resultiert folgender Gedanke:

```
double zufälligerWert = Math.random();
if((zufälligerWert < 0.1) {
    return 10;
} else {
    return 20;
}
```

Beste Grüße,
Jar


----------



## kneitzel (17. Feb 2016)

Die Idee von Blender3D ist gut, aber es sollte dann sein: 1 -> 10 und 2-10 -> 20. 
Die chance von jeder Zahl bei dem Bereich von 1-10 ist 10%. Also darf die 10 nur eine Ziffer bekommen und die 20 muss 9 Ziffern bekommen. (Und nicht 2 und 8 was 20% / 80% entsprechen würde!)


----------



## Blender3D (17. Feb 2016)

zahl = ZufallsZahlVonBis( 1,10 );
wenn ( zahl in (1,2) ) Ergebnis = 10;
sonst Ergebnis = 20;
--> 10 mit 20% Wahrscheinlichkeit und 20 mit 80% Wahrscheinlichkeit.

Für Deine Aufgabe musst Du nur die Wahrscheinlichkeit anpassen.


----------



## Blender3D (17. Feb 2016)

kneitzel hat gesagt.:


> Die Idee von Blender3D ist gut, aber es sollte dann sein: 1 -> 10 und 2-10 -> 20.
> Die chance von jeder Zahl bei dem Bereich von 1-10 ist 10%. Also darf die 10 nur eine Ziffer bekommen und die 20 muss 9 Ziffern bekommen. (Und nicht 2 und 8 was 20% / 80% entsprechen würde!)


Danke kneitzel, mein Gedanke war aber, dass er selbst darauf kommt


----------



## NeX (17. Feb 2016)

Vielen, Vielen Dank! Da wäre ich jetzt aus dem Stegreif echt nicht selbst draufgekommen! 
Funktioniert einwandfrei


----------



## kneitzel (17. Feb 2016)

Sorry, das hab ich auch erst bei Deinem zweiten Post gemerkt. Der erste sah nur nach reiner Lösung aus ohne Erwähnung der 20 / 80 Prozent so dass ich da einen Fehler korrigieren wollte.


----------



## Blender3D (17. Feb 2016)

Nop


----------



## Xyz1 (17. Feb 2016)

Legt man eine Kurve durch, stellen sich ja alle Wahrscheinlichkeiten so dar:

```
x    y
  0  -70,000000
  1  -62,000000
  2  -54,000000
  3  -46,000000
  4  -38,000000
  5  -30,000000
  6  -22,000000
  7  -14,000000
  8   -6,000000
  9    2,000000
 10   10,000000
 11   18,000000
 12   26,000000
 13   34,000000
 14   42,000000
 15   50,000000
 16   58,000000
 17   66,000000
 18   74,000000
 19   82,000000
 20   90,000000
 21   98,000000
 22  106,000000
 23  114,000000
 24  122,000000
 25  130,000000
 26  138,000000
 27  146,000000
 28  154,000000
 29  162,000000
 30  170,000000
 31  178,000000
 32  186,000000
 33  194,000000
 34  202,000000
 35  210,000000
 36  218,000000
 37  226,000000
 38  234,000000
 39  242,000000
 40  250,000000
 41  258,000000
 42  266,000000
 43  274,000000
 44  282,000000
 45  290,000000
 46  298,000000
 47  306,000000
 48  314,000000
 49  322,000000
 50  330,000000
 51  338,000000
 52  346,000000
 53  354,000000
 54  362,000000
 55  370,000000
 56  378,000000
 57  386,000000
 58  394,000000
 59  402,000000
 60  410,000000
 61  418,000000
 62  426,000000
 63  434,000000
 64  442,000000
 65  450,000000
 66  458,000000
 67  466,000000
 68  474,000000
 69  482,000000
 70  490,000000
 71  498,000000
 72  506,000000
 73  514,000000
 74  522,000000
 75  530,000000
 76  538,000000
 77  546,000000
 78  554,000000
 79  562,000000
 80  570,000000
 81  578,000000
 82  586,000000
 83  594,000000
 84  602,000000
 85  610,000000
 86  618,000000
 87  626,000000
 88  634,000000
 89  642,000000
 90  650,000000
 91  658,000000
 92  666,000000
 93  674,000000
 94  682,000000
 95  690,000000
 96  698,000000
 97  706,000000
 98  714,000000
 99  722,000000
100  730,000000
```

10 wird also mit 10 % Wahrscheinlichkeit, 20 mit 90 % Wahrscheinlichkeit gezogen.

Summiert man die y-Spalte, fällt schnell auf, die Wahrscheinlichkeiten ergeben in Summe nicht 100. Das ist für eine ungleiche Verteilung "suboptimal".

```
private static float zieheSchief() {
        if (Math.random() < 0.1) {
            return 10;
        } else {
            return 20;
        }
    }

    private static void ziehePaarMal() {
        for (int i = 0; i < 10; i++) {
            System.out.println(zieheSchief());
        }
    }
```


```
20.0
10.0
20.0
20.0
20.0
20.0
20.0
20.0
10.0
20.0
```

Da kann man gut feststellen, 2x 10 und 8x20 ...


----------



## Neumi5694 (21. Feb 2016)

0 ... 100 geht natürlich nicht.
Der korrekte Umweg führt über 0-99, dann Nachkommastellen abschneiden, dann +1 ... falls man Wert darauf legt, Zahlen von 1-100 zu sehen. 0-99 funktioniert natürlich genau so gut.


----------



## JStein52 (21. Feb 2016)

Neumi5694 hat gesagt.:


> 0 ... 100 geht natürlich nicht.


Falscher Thread ???


----------



## Neumi5694 (23. Feb 2016)

JStein52 hat gesagt.:


> Falscher Thread ???


Nein, wieso?
101 Möglichkeiten wären Unsinn.


----------



## JStein52 (23. Feb 2016)

Ach so, das bezog sich auf den Beitrag mit der Summe der Wahrscheinlichkeiten ??



DerWissende hat gesagt.:


> Da kann man gut feststellen, 2x 10 und 8x20 ...


Da war mir noch mehr unklar. Z.B. was soll uns diese Aussage sagen ? Mit dem Code der darüber steht hat das wohl nichts zu tun ??!!


----------



## Neumi5694 (23. Feb 2016)

Auf einen davon, ja.

Ich hab mal schnell eine etwas allgemeinere Funktion zusammengebastelt, die zufällige Ergebnisse mit festgelegten Wahrscheinlichkeiten ermittelt. Das geht sicher auch effizienzer, Ergebnisse mit der Wahrscheinlichkeit 0 sollten der Lesbarkeit halber bei der Auswertung explizit ausgeschlossen werden.

```
/**
     *
     * @param possibleResults ... Aus Faulheit eine Hashmap, man könnte natürlich auch eien Klasse definieren, die ein Ergebnis und dessen Wahrscheinlichkeit beinhaltet ein Array solcher Objekte übergeben
     * <br> Als Wahrscheinlichkeit von result = Math.abs(possibleResult.get(result))
     * <br> Also bitte nicht null als Wahrscheinlichkeit eintragen
     * @return
     */
    public static <T> T getRandomItemOf(Map<T, Double> possibleResults) {
        if (possibleResults == null || possibleResults.isEmpty()) {
            return null;
        }
        //Summe der Wahrscheinlichkeiten ermitteln
        double totalWeight = 0d;
        for (Map.Entry<T, Double> oneItem : possibleResults.entrySet()) {
            totalWeight += Math.abs(oneItem.getValue()); //eventuell hier testen, ob irgend ein Genie null übergeben hat
        }
        if (totalWeight == 0) {
            //ohne diese Eingreifen würde immer der erste gelistete Wert geliefert, wenn alle Wahrscheinlichkeiten 0 sind.
            return null;
        }
        double randomNumber = Math.random() * totalWeight; //der Maximalwert wird nie erreicht, 0 kann hingegen vorkommen
        double sumPreviousWeights = 0d;
        for (Map.Entry<T, Double> oneItem : possibleResults.entrySet()) {
            sumPreviousWeights+= Math.abs(oneItem.getValue()); //wieder eventuell auf null testen
            if (randomNumber < sumPreviousWeights) {
                return oneItem.getKey();
            }
        }
        return null;
    }
    public static void main(String... args) {
        HashMap<Integer, Double> possibleResults = new HashMap<>();
        possibleResults.put(10, 20d);
        possibleResults.put(20, 80d);
        final int nTests = 1000000;
        int n10 = 0;
        int n20 = 0;
        for (int i = 0; i < nTests; i++) {
            Integer result = getRandomItemOf(possibleResults);
            if (result == 10) {
                n10++;
            } else if (result == 20) {
                n20++;
            }
        }
        //falls alles klappt, sollte das Ergebnis "10" ca. nTests*0.2 geliefert worden sein.
        System.out.printf(Locale.US, "10 war das Ergebnis von %d aus %d Ziehungen = %.2f Prozent\n", n10, nTests, 100.0 * n10 / nTests);
        System.out.printf(Locale.US, "20 war das Ergebnis von %d aus %d Ziehungen = %.2f Prozent\n", n20, nTests, 100.0 * n20 / nTests);
    }
```



Ausgabe:

10 war das Ergebnis von 199906 aus 1000000 Ziehungen = 19.99 Prozent
20 war das Ergebnis von 800094 aus 1000000 Ziehungen = 80.01 Prozent


----------



## JStein52 (23. Feb 2016)

Ja, genau. So macht das Sinn !!


----------

