Autor Beitrag
jackie05
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: Mo 08.08.11 20:37 
Hallo,
gibt es eine möglichkeit 3 Zufallszahlen zu erzeugen die zusammen 50 ergeben?
Die Zufallszahlen sollen zwischen 5 und 50 liegen, z.B:
Zufallszahl 1: 7
Zufallszahl 2: 26
Zufallszahl 3: 17

oder so

Zufallszahl 1: 5
Zufallszahl 2: 37
Zufallszahl 3: 8

Die 3 Zufallszahlen sollen halt immer Zusammengerechnet 50 ergeben.

Wie könnte man das realisieren?

Ich bedanke mich schonmal im Voraus.

MfG
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mo 08.08.11 20:38 
Moin!

Erzeuge zwei und bilde die Differenz. :idea: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
jackie05 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: Mo 08.08.11 20:42 
Danke Dir.
Ich denke nicht das es so gehen könnte, weil wenn die 2 Zufallszahlen 25 oder mehr haben, dann sind es ja schon 50 oder mehr.

Wie soll ich die ambesten erzeugen?

MfG
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mo 08.08.11 21:08 
Dann überlege einmal, wie du die Erzeugung der Zahlen anhand der bereits erzeugten einschränken musst, damit so etwas nicht auftritt. Die Tripel sind dann nicht mehr perfekt gleichverteilt, aber ich nehme mal an, das ist nicht ganz so wichtig?

_________________
>λ=
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Mo 08.08.11 21:38 
Wenn man Zufallszahlen einzuschränken versucht, dann schränkt man auch den Zufall ein.

user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Die Tripel sind dann nicht mehr perfekt gleichverteilt, aber ich nehme mal an, das ist nicht ganz so wichtig?


Nicht nur "nicht perfekt", sondern gar nicht mehr. Bereits die Summe zweier Gleichverteilungen führt zu einer Dreiecksverteilung. Addiert man noch eine gleichverteilte Zufallsgröße dazu, wird die Verteilung noch schmaler, man entfernt sich vom gleichverteilten Zufall noch mehr.
gehstock
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19
Erhaltene Danke: 2



BeitragVerfasst: Mo 08.08.11 21:42 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
a := Random(40);// die Max 50 - 2x min 5
 b := Random(45-a); //die Max 50 - 1x min 5 - a
 c := 50 -(a+b);// der rest von 50
 edt1.Text := IntToStr(a);
 edt2.Text := IntToStr(b);
 edt3.Text := IntToStr(c);
end;


Edit: ups Fehler so sind zu kleine Werte möglich

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Repeat
    a := Random(40);
  until a >= 5;
  Repeat
    b := Random(45 - a);
  until b >= 5;
  c := 50 - (a + b);
  edt1.Text := IntToStr(a);
  edt2.Text := IntToStr(b);
  edt3.Text := IntToStr(c);
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Mo 08.08.11 22:09 
user profile icongehstock hat folgendes geschrieben Zum zitierten Posting springen:

ausblenden Delphi-Quelltext
1:
2:
3:
Repeat
    a := Random(40);
  until a >= 5;


Und so sind überflüssige Schleifendurchläufe möglich! Nimm doch gleich besser: a:=5+random(35) und b:=5+random(40-a).

c wird keine gleichverteilte, sondern eine dreiecksverteilte Zufallszahl sein (s.o.).
jackie05 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: Mo 08.08.11 22:17 
Genau das hatte ich versucht gehabt und irgendwie hat es nicht so richtig funktioniert.

Vielen Dank für die Hilfe.

MfG
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Mo 08.08.11 22:20 
Was soll daran "irgendwie nicht richtig funktionieren"? Natürlich funktioniert so etwas! Mit der Addition wird die (gleichverteilte) Zufallsvariable auf dem Zahlenstrahl um eben 5 nach oben verschoben, also erhöht. Damit die andere, die obere Spitze auch korrekt ist, muß man den Zufallszahlenbereich eben um genau den gleichen Betag reduzieren.

Ohne Quellcode ist nicht ersichtlich, wo Dein Problem steckt.
jackie05 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 357



BeitragVerfasst: Mo 08.08.11 23:28 
Danke Dir.

Ich bin dabei ein Spiel zu schreiben mit jeweils 3 Runden, jede Runde wird eine Zahl generiert und alle 3 Runden sollen dann dementsprechend mit den generierten Zahlen die Zahl 50 ergeben.

So hatte ich es testhalber versucht:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
  if (RundeNr = 1then
  begin
    Zahl := random(40-5)+(5);
    tmpZahl := (50-Zahl);
  end;
  if (RundeNr = 2then
  begin
    Zahl := random((tmpZahl div 2)-5)+(5);
    tmpZahl := (tmpZahl-Zahl);
  end;
  if (RundeNr = 3then
  begin
    Zahl := tmpZahl;
    tmpZahl := (tmpZahl-Zahl);
  end;


leider ohne erfolg.

Jetzt habe ich den vorschlag von @gehstock eingebaut und nun funktioniert es.

Vielen Dank.

MfG
Delphi-Laie
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 1600
Erhaltene Danke: 232


Delphi 2 - RAD-Studio 10.1 Berlin
BeitragVerfasst: Mo 08.08.11 23:46 
Implementiere statt der drei Abfragen bezüglich der Rundennummer besser nur eine (1) case-Anweisung.

Daß gestocks Code funktioniert, mag schon sein, doch das widerlegt nicht, daß Zufallszahlen in einem bestimmten Zahlenbereich mit der Methode (nicht im objektorientierten Sinne gemeint), wie ich Sie zeigte, generierbar sind. Der Fehler muß also woanders stecken. Vielleicht zeigst Du auch noch Deinen nunmehr erfolgreichen Code, damit man vergleichen kann.

Postscriptum: Das @-Zeichen (at = an (... gerichtet)) vor gehstock ist wahrlich überflüssig, da Du ihn offensichtlich nicht ansprichst.
Blup
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 174
Erhaltene Danke: 43



BeitragVerfasst: Fr 12.08.11 15:55 
a:=5+random(35) liefert nur Zufallszahlen im Bereich 5..39, die 40 wird niemals geworfen.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
a := random(36);       // a = 0..35
b := random(36 - a);   // b = 0..35
a := a + 5;            // a = 5..40
b := b + 5;            // b = 5..40
c := 50 - (a + b);     // c = 5..40

Dieser Ansatz kann aber keine gleichverteilte Zufallszahlen liefern:
ausblenden Quelltext
1:
2:
3:
4:
Wahrscheinlichkeit für die Zahl 40
a -> (1/36)            // erster Wurf 40
b -> (1/36) * (1/36)   // erster Wurf 5  + zweiter Wurf 40
c -> (1/36) * (1/36)   // erster Wurf 5  + zweiter Wurf 5

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
Wahrscheinlichkeit für die Zahl 5
a -> (1/36)            // erster Wurf 5
b -> (36/36) * (1/36)  // erster Wurf beliebig + zweiter Wurf 5
c -> (1/36) * (1/36) + // erster Wurf 5  + zweiter Wurf 40
     (1/36) * (1/35) + // erster Wurf 6  + zweiter Wurf 39
     (1/36) * (1/34) + // erster Wurf 7  + zweiter Wurf 38
     ...
     (1/36) * (1/1)    // erster Wurf 40 + zweiter Wurf 5
.
     oder (1/36) * 36-te harmonische Zahl // "Harmonische Reihe"
.
                  n
     (1/36) * ( summe  1/k )
                k = 1


---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

Reihe der möglichen Kombinationen
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
 a    b    c
-------------
 5    5   40 --  36 x 5
 5    6   39  |
 5    7   38  |
 5    8   37  |
 5    9   36  |
...           |
 5   40    5 -            
 6    5   39 --  35 x 6
...           |
 6   39    5 -
 7    5   38 --  34 x 7
...           |
 7   38    5 -
...
38    5    7 --   3 x 38
38    6    6  |
38    7    5 -
39    5    6 --   2 x 39
39    6    5 -
40    5    5 --   1 x 40


Betrachtet für die Werte der Variable a jeweils die Anzahl der Kombinationen, können diese so zu Pärchen zusammenfasst werden, daß die Summe der Kombinationen für jedes Pärchen konstant ist:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
 5 (36)   40 (1)
 6 (35)   39 (2)
 7 (34)   38 (3)
...
22 (19)   23 (18)
.
Gesamtanzahl der Kombinationen
(36 / 2) * (36 + 1) = 666

Damit ergibt sich bei einer gleichmäßigen Verteilung die Wahrscheinlichkeit
 5 -> 36/666
40 ->  1/666


Die einfachste Lösung des Problems ist, jeweils eine Kombination aus der Menge aller Kombinationen auszuwählen.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
const
  ERROR_PARAMETER_RANGE =
    'Paramter außerhalb des gültigen Bereichs';
.
procedure GetDreierKomination50(n: Integer; out a, b, c: Integer);
var
  x1, x2: Integer;
begin
  if (n < 0or (n > 665then
    raise Exception.Create(ERROR_PARAMETER_RANGE);
.
  x1 := (n div 37);      // x1 = 0..17
  x2 := (n mod 37);      // x2 = 0..36
.
  if x2 < (36 - x1) then
  begin
    a := x1;             // a = 0..17
    b := x2;             // b = 0..35
  end
  else
  begin
    a := 35 - x1;        // a = 35..18
    b := x2 - (36 - x1); // b =  0..17
  end;
.
  a := a + 5;            // a = 5..40
  b := b + 5;            // b = 5..40
  c := 50 - (a + b);     // c = 5..40
end;  
.
procedure TForm1.ButtonTestClick(Sender: TObject);
var
  n, a, b, c: Integer;
begin
  // Test: alle Kombinationen ausgeben
  Memo1.Lines.Clear;
  for n := 0 to 665 do
  begin
    GetDreierKomination50(n, a, b, c);
    Memo1.Lines.Add(Format('%2d %2d %2d', [a, b, c]));
  end;
  // zufällige Kombination:
  // GetDreierKomination50(Random(666), a, b, c);
end;