Hilfe bei einem Algorithmus

Hi

Die Berechnung der Wahrscheinlichkeiten ist soweit Richtig meiner Meinung nach zur Berechnung was Gewürfelt wird hätte ich auch eine Ideee muss dazu nur wissen ob

float fRand() (liefert eine Zufallszahl aus dem Intervall [0,1[) zur Verfügung.

stimmt oder ob du dich verschriebene hast und Intervall [0,1] da stehen sollte?

MFG NeonXT


PS: War die Lösung von der vorherigen aufgaben den richtig für den Prof
 
Nein ist schon richtig so, also 0<n<=1

Ich würd ja die jew. Wahrscheinlichkeiten in ein Array speichern und immer neu berechnen, aber wie das ganze auf den Würfel anwenden...?
 
Zuletzt bearbeitet:
Also meine Idee wäre du speicherst wie gesagt in ein Array mit der größe 6 die jeweiligen Prozentsätze für die Zahlen.

Daraus sollte sich dann nach deinem Beispiel so etwas ergeben, nehme mal dein Beispiel oben aus der rechneung nach einmal Würfeln in diesem Beispiel nehme ich mal die 4 die gewürfelt wurde.

Soll nur verdeutlichen was in dem Array steht
prozentwerte[0] = 0,1833333 //11/60
prozentwerte[1] = 0,1833333 //11/60
prozentwerte[2] = 0,1833333 //11/60
prozentwerte[3] = 0,0833333 //1/12
prozentwerte[4] = 0,1833333 //11/60
prozentwerte[5] = 0,1833333 //11/60

So wenn man die ganzen werte nun addiert bekommt man als Ergebnis 1,0.

Und jetzt kommt meine Idee:
Lass dir von fRand() eine Zahl geben.
Jetzt guckst du wo sich die Zahl befindet in dem du das array durchläufst.


Code:
int gewürfelteZahl = 0;
int zaehler = 0;
float dezimalwert = 0;
float zufallsZahl = fRand();
do
{
    dezimalwert += prozentwerte[zaehler];
    if(zufallsZahl<=dezimalwert)
         gewürfeltezahl = zaehler+1;

    zaehler++;
}while(gewürfelteZahl ==0)

und hiernach musste wieder die Prozentwerte im Array ändern da man erst Würfelt und dann sich die Wahrscheinlich keiten ändern da die Veränderung der Wahrscheinlich keit des Würfelergebnisses abhängig ist. Hoffe das dir das ein bisschen hilft.

Es gibt auch noch die Möglichkeit mit Prozentwerten zu rechnen aber mit einem hohen 10er faktor also nicht 0,1833333 sondern 1833333 dann muss halt nur die andere Funktion benutzt werden.
 
Zuletzt bearbeitet:
Danke wieder mal für deine schnelle Antwort :D

Code:
int gewürfelteZahl = 0;
int zaehler = 0;
float dezimalwert = 0;
float zufallsZahl = fRand();
do
{
    dezimalwert += prozentwerte[zaehler];
    if(zufallsZahl<=dezimalwert)
         gewürfeltezahl = zaehler+1;

    zaehler++;
}while(gewürfelteZahl ==0)

Hmm das versteh ich nicht so ganz. Wenn jetzt beim ersten "Wurf" die Random-Zahl eine Zahl grösser 1/6 ist, dann geh ich doch gleich wieder aus der Schleife raus mit gewürfelteZahl=0 ...

Außerdem ist mir auch nicht klar wie hier die Wahrscheinlichkeiten Einfluss aufs Würfeln haben...
 
Danke wieder mal für deine schnelle Antwort :D



Hmm das versteh ich nicht so ganz. Wenn jetzt beim ersten "Wurf" die Random-Zahl eine Zahl grösser 1/6 ist, dann geh ich doch gleich wieder aus der Schleife raus mit gewürfelteZahl=0 ...

Außerdem ist mir auch nicht klar wie hier die Wahrscheinlichkeiten Einfluss aufs Würfeln haben...

Also der Quellcode stellt nur einen Wurf da gewürfelteZahl ist immer 0 außer die ZufallsZahl ist kleiner gleich dem Nächsten Definitionsbereich, sollte die Zeichnung erklären.

Die Zeichnung im Anhang sollte dir auch erklären was der Code mit der Wahrscheinlichkeit haben soll.

Es zeigt die Werte nach einmal Würfel einer 4, wobei der Balken für die 4 nun kleiner ist und somit auch ein kleinerer Bereich bzw WerteIntervall existiert, also auch eine kleinere chance eine 4 zu Würfeln.
.
Hoffe das dir diese Zugabe ein wenig mehr hilft meinen Ansatz zu verstehen.

Wenn sich noch fragen ergeben sollten dann wie immer einfach fragen :D.
 

Anhänge

also die Berechnung sieht glaub ich so aus:
Wird eine Zahl gewürfelt, sinkt die Wahrscheinlichkeit dieser Zahl noch einmal gewürfelt zu werden um die Hälfte (zB 1?6 ? 1?12). Die andere Hälfte der Wahrscheinlichkeit wird auf die übrigen Zahlen gleichmäßig verteilt (zB 1?6 ?1?6+(1?12)/5=11?60).


aber wie ich die Wahrscheinlichkeit auf die Random-Zahlen anwende ist mir bis jetzt ein Rätsel....

Wenn ich dich richtig verstanden habe, probier doch mal das:
Dann probier doch mal, die Wahrscheinlichkeit aller Zahlen 1-6 als Bruch (!) zu behalten.
Beim "Würfeln" erstellst du ein Array mit der Länge: (alle Wahrscheinlichkeiten (>als double) summiert)*(kgV aller Nenner der Wahrscheinlichkeiten)
Dann fügst du in das Array die Zahlen 1-6 ein, und zwar jede Zahl so oft, wie sie bei der Wahrscheinlichkeit den Zähler des Bruchs hat, mal das kgV. (z.B. Zähler = 3, also 3*kgV(Nenner1, Nenner2, ...) mal hinein).
Dann suchst du mit zB. array[(int)(Math.random()*array.length)] eine beliebige Zahl heraus und du hast dein Ergebnis. ;)
Ich hoffe, dass ich es verständlich erklärt habe (EDIT: Wenn ich mir den Beitrag anschaue, glaube ich das nicht :D) und dass es funktioniert. :)
Wenn dir dein Array zu groß wird (wegen zu komplizierten Nennern der Brüche) kannst du immer mal wieder die Brüche kürzen lassen. ;)
 
Danke für die Zeichnung, jetzt hab ichs gecheckt!!;-)

und wieder mal vielen Dank für den Denkanstoss *thumbup*

Und Danke auch dir JellySheep
 
Zuletzt bearbeitet:
Sind deine Fragen jetzt beantwortet? Dann markiere bitte noch das Thema als "erledigt". :)

Wenn nicht, habe ich hier noch einen vereinfachten Code, die Lösung aus meinem anderen Beitrag kannst du vergessen. :-)

// EDIT:
Hier ist ein vollständiger Code, um den Algorithmus zu testen und mit dem "normalen" Würfeln zu vergleichen.
Java:
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.UIManager;

public class Wuerfel {
    double wahrscheinlichkeit[] = new double[] { 1d / 6d, 1d / 6d, 1d / 6d,
            1d / 6d, 1d / 6d, 1d / 6d };
    public static final boolean anpassen = true;
    public static final int nachkommastellen = 2;
    public static final int divisor = 2;

    public int wuerfel() {
        double random = Math.random();
        double tmp = 0;
        tmp += wahrscheinlichkeit[0];
        if (random < tmp) {
            return anpassen(1);
        }
        tmp += wahrscheinlichkeit[1];
        if (random < tmp) {
            return anpassen(2);
        }
        tmp += wahrscheinlichkeit[2];
        if (random < tmp) {
            return anpassen(3);
        }
        tmp += wahrscheinlichkeit[3];
        if (random < tmp) {
            return anpassen(4);
        }
        tmp += wahrscheinlichkeit[4];
        if (random < tmp) {
            return anpassen(5);
        }
        return anpassen(6);
    }

    public int anpassen(int augenzahl) {
        if (anpassen) {
            wahrscheinlichkeit[augenzahl - 1] /= divisor;
            double tmp = wahrscheinlichkeit[augenzahl - 1]*(divisor-1) / 5;
            for (int i = 1; i < 6; i++) {
                wahrscheinlichkeit[(augenzahl - 1 + i) % 6] += tmp;
            }
        }
        return augenzahl;
    }

    public static void main(String[] args) {
        try {
            UIManager
                    .setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        } catch (Exception e) {
            e.printStackTrace();
        }
        int x[] = new int[6];
        Wuerfel w = new Wuerfel();
        int wuerfe = 10000000;
        JFrame f = new JFrame("Würfeln...");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JProgressBar pb = new JProgressBar(0, wuerfe);
        pb.setStringPainted(true);
        f.add(pb);
        f.setSize(300, 70);
        f.setVisible(true);
        for (int i = 0; i < wuerfe; i++) {
            x[w.wuerfel() - 1]++;
            pb.setValue(i);
        }
        f.setVisible(false);
        for (int i = 0; i < 6; i++) {
            System.out.println("Abweichung der rel. Häufigkeit für " + (i + 1) + ": "
                            + ((((double) ((int) (((6d * x[i] / wuerfe) - 1) * 100 *
                            Math.pow(10, nachkommastellen))))) /
                            Math.pow(10, nachkommastellen)) + " %");
        }
        System.exit(0);
    }
}
Mit der Variable "anpassen" wird der Algorithmus ein-/ausgeschaltet, mit "nachkommastellen" wird die Genauigkeit des Ergebnisses eingestellt, mit divisor wird der Faktor geregelt, um der die Wahrscheinlichkeit der gewürfelten Zahl verringert wird.

Ergebnis bei "normalem" Würfeln:
Abweichung der rel. Häufigkeit für 1: -0.01 %
Abweichung der rel. Häufigkeit für 2: 0.1 %
Abweichung der rel. Häufigkeit für 3: 0.0 %
Abweichung der rel. Häufigkeit für 4: 0.09 %
Abweichung der rel. Häufigkeit für 5: -0.2 %
Abweichung der rel. Häufigkeit für 6: 0.02 %
Mit Algorithmus:
Abweichung der rel. Häufigkeit für 1: 0.04 %
Abweichung der rel. Häufigkeit für 2: -0.03 %
Abweichung der rel. Häufigkeit für 3: 0.01 %
Abweichung der rel. Häufigkeit für 4: -0.01 %
Abweichung der rel. Häufigkeit für 5: -0.05 %
Abweichung der rel. Häufigkeit für 6: 0.04 %

Es ist interessant, dass die rel. Häufigkeit gleich bleibt, das hätte ich nicht gedacht...
Auch wenn der Algorithmus ein kleines bisschen länger dauert, ist er dennoch irgendwie "realistischer".
 
Zuletzt bearbeitet:
Hier ein anderer Ansatz.
Du kannst die Anzahl der Seiten anpassen. Bei nur zwei Seiten sieht man schön, wie das ganze funktioniert.

Java:
public class Dice
{
	private double[] side;

	public Dice()
	{
		this(6);
	}
	public Dice(int sides)
	{
		side = new double[sides];
		double initVal = (double)1/sides;
		for(int i = 0; i < sides; i++)
			side[i] = initVal;
	}
	public int rollDice()
	{
		double diced = Math.random();
		double history = 0d;
		for(int i = 0; i < side.length; i++)
		{
			if(diced <= side[i] + history)
			{
				changeChances(i);
				return i + 1;
			}
			history += side[i];
		}
		return 0;
	}
	public void changeChances(int diced)
	{
		double change = side[diced] / 2;
		for(int i = 0; i < side.length; i++)
		{
			if(i == diced)
			{
				side[diced] /= 2;
			}
			else
			{
				side[i] += change / (side.length - 1);
			}
		}
	}
	public void getChances()
	{
		System.out.println("Neue Chancenverteilung:");
		for(int i = 0; i < side.length; i++)
		{
			System.out.println("Seite " + (i+1) + " = " + side[i] * 100 + "%");
		}
		System.out.println();
	}
	public static void main(String[] args)
	{
		Dice dice = new Dice(2);
		dice.getChances();
		for(int i = 0; i < 6; i++)
		{
			System.out.println("Seite " + dice.rollDice() + "  gewürfelt");
			dice.getChances();
		}
	}
}

Resultat
Code:
Neue Chancenverteilung:
Seite 1 = 50.0%
Seite 2 = 50.0%

Seite 1 gewürfelt
Neue Chancenverteilung:
Seite 1 = 25.0%
Seite 2 = 75.0%

Seite 2 gewürfelt
Neue Chancenverteilung:
Seite 1 = 62.5%
Seite 2 = 37.5%
 
Zuletzt bearbeitet:
Zurück