Mit nextGaussian() positive Zahlen erzeugen?

Bitte aktiviere JavaScript!
Bei ng(10, 11) hält es allerdings nicht an...
Die Wahrscheinlichkeit, dass Du eine Zufallsvariable > 4,09 erhältst, ist nahezu 0. Siehe https://de.wikipedia.org/wiki/Standardnormalverteilungstabelle.

Sollte aber klappen, den Erwartungswert in die Mitte des gewünschten Intervalls zu "schieben" und die Standardabweichung anzupassen (zB 1/6 der Interfvallgröße). Wenn man alles außerhalb liegende abschneidet, verliert man ein paar Promille (je nach Standardabweichung), aber nutzen lassen sollte es sich trotzdem.
So sehe ich das auch. Wenn man nur eine Seite abschneidet, dürfte sich der Erwartungswert verschieben. Wenn man sich überlegt, dass es fast unmöglich ist, Werte jenseits +/- 5 zu erhalten, spielt das für Erwartungswerte > 5 praktisch keine Rolle.

Falls es jemanden interessiert, hier der Octave Code (Achtung: hingerotzt) für den Graphen von oben:
Code:
function retval = incomings(n,m,s)
    X=zeros(n,1);
    for i = 1:n
        do
           v = randn()*s+m;
        until (v >= 0)
        X(i) = round(v);
    endfor
    retval = X;
endfunction


I=incomings(10000, 1500, 500);
X=sort(I);
total=sum(X)
C=cumsum(X)/total;
Y=[0;accumarray(ceil((1:rows(C)) / 1000)(:), C)];

I=abs(randn(10000,1))*500+1500;
X=sort(I);
total=sum(X)
C=cumsum(X)/total;
Z=[0;accumarray(ceil((1:rows(C)) / 1000)(:), C)];
hf = figure()
hold on 
plot(0:0.1:1, Y/max(Y), "markersize", 10, "o-")
plot(0:0.1:1, Z/max(Z), "markersize", 10, "xr-")
hold off
print(hf, "lorenz.png", "-dpng")

Wenn ich mich nicht vertan habe, sollte das ein normalverteiltes Zufallseinkommen von 10.000 Personen simulieren mit einem Durchschnittseinkommen von 1.500 €, wobei knapp 70 % im Bereich zwischen 1.000 € und 2.000 € verdienen.

Aber Achtung: ich kenne mich mit dem Zeug echt nicht aus.
 
A

Anzeige


Vielleicht hilft dir dieser Kurs hier weiter: (hier klicken)
Etwa so sollte das klappen:

Java:
import java.util.*;

public class NormalVerteilung {

    private final double from;

    private final double to;

    private final Random random = new Random();

    public NormalVerteilung(final double from, final double to) {
        this.from = from;
        this.to = to;
    }

    public double next() {
        final double expectation = from + (to - from) / 2;
        final double stdDev = (to - from) / 6; //knapp 2‰ liegen dann außerhalb, uU anpassen

        double result;
        do {
            result = random.nextGaussian() * stdDev + expectation;
        } while (result < from || result > to);

        return result;
    }

    public static void main(String[] args) {
        final NormalVerteilung normalVerteilung = new NormalVerteilung(5, 10);
        for (int i = 0; i < 1000; i++) {
            System.out.println(normalVerteilung.next());
        }
    }

}
 
Achtung Mathematik-DAU: Wofür ist nochmal das "stdDev" nötig?
Achtung, auch Mathematik-DAU:

Hier hat @mihe7 den Hintergrund erklärt.

Man hat einen Erwartungswert und die Standardabweichung. Ca. 69 % der normalverteilten Werte liegen im Bereich des Erwartungswerts +/- Standardabweichung. Verdoppelt man die Standardabweichung, liegen etwa 95 % der Werte in dem sich ergebenden Bereich. Man kann das Intervall aber beliebig groß wählen, man wird nie 100 % erreichen.
Will man dann zB, dass 69% aller Werte im Intervall liegen, muss das Intervall zwei Standardabweichungen groß sein (da Mitte und Erwartungswerts +/- Standardabweichung)
Oder andersrum, wenn das Intervall fest ist, müsste die Standardabweichung so gewählt sein, dass sie genau zwei mal in's Intervall passt.


Mit 3 Standardabweichungen hat man über 99,7% der Werte, deshalb sind's oben die 1/6 des Intervalls.
 
Juhu, fertig :)
Java:
	public static double ng(double a, double b) {
		double eps = 0.001;
		if (!(a + eps < b)) {
			throw new IllegalArgumentException("a must be lower than b");
		}
		double c = -(b - a) / 2;
		double d = +(b - a) / 2;
		Random r = new Random();
		double g = r.nextGaussian();
		while (g < c || g > d) {
			g = r.nextGaussian();
		}
		return g + d + a;
	}

	public static void main(String[] args) {
		double d = 0;
		for (int i = 0; i < 10000; i++) {
			d += ng(0.10, 0.11) / 10000;
		}
		System.out.println(d);
		d = 0;
		for (int i = 0; i < 10000; i++) {
			d += ng(10, 11) / 10000;
		}
		System.out.println(d);
		d = 0;
		for (int i = 0; i < 10000; i++) {
			d += ng(-11, -10) / 10000;
		}
		System.out.println(d);
	}
Code:
0.10501...
10.502...
-10.497...
(Muss ich mir mal in meinem Utility Kasten speichern :)
 
Da ist keine Abweichung um 1

Kann höchstens noch ein Streckungsfaktor hinzufügen... Je nachdem wie weich oder hart die Parabel sein soll...
 
Er meint, dass nextGaussian() einen Zufallswert mit einer Standardabweichung von 1 (um den Wert 0 herum) liefert. Deine Methode macht zwei Dinge: erstens den Erwartungswert in die Mitte des Intervalls verschieben, zweitens nur Werte innerhalb des Intervalls zurückgeben. Wenn Du also z. B. ein Intervall von [0, 20] angibst, werden sich die Zufallswerte mit ebenfalls ca. 70 % im Intervall [9, 11] bewegen.
 
Ok, das ist Intervallabhängig. Zum Beispiel wählt man -5 bis +5:
Java:
double[] d = new double[11];
for (int i = 0; i < 1000; i++) {
	int e = (int) Math.round(ng(-5, +5)) + 5;
	d[e] += 1.0 / 1000.0;
}

for (int i = 0; i < d.length; i++) {
	double e = d[i];
	System.out.println(((i - 5) + " " + (e)));
}
Code:
-5 0.0
-4 0.001
-3 0.009 (Nullen entfernt)
-2 0.067
-1 0.237
0 0.379
1 0.231
2 0.073
3 0.003
4 0.0
5 0.0
Das entspricht fast schon dieser Normalverteilung...

Möchte man das nicht, könnte man die Werte doch "strecken" (also auseinander-ziehen) mithilfe diese "Streckungsfaktors"?
 
Das entspricht fast schon dieser Normalverteilung...
Das hab ich nicht in Zweifel gezogen ;)

Aber nimm zb mal 0-1 (und skalier das für die Ausgabe auf 0-10), dann sieht man, was ich meine. Oder alternativ 0-100 (und skaliert auf 0-10).


Das soll keineswegs heißen, dass es falsch ist - man muss es nur wissen und beachten.
Je nach Anwendungsfall macht das eben Probleme.
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben