Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi randomize problem (https://www.delphipraxis.net/142720-randomize-problem.html)

painrestricter 2. Nov 2009 14:17


randomize problem
 
servuß

ich bin neu hier und programmier noch nicht so lange, deswegen brauch ich euch ;)

also ich will ein kleines programm schreiben, dass mir lottozahlen generiert.
die basis steht ja schon, funktionieren tuts ja auch, aber obwohl ich eine if schleife für die 0 rein hab (die gibt es ja bei lotto nicht) kommt sie immer wieder.

weiterhin will ich das so machen, dass ne zahl nur einmal vorkommt. manchmal kommen 2 gleich zahlen vor.

hier mal der (kleine) sourcecode


Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
randomize;
for i := 1 to 6 do begin
test := random(49);
if test = 0 then begin
memo1.clear;
test := random(49);
if test < 6 then begin
memo1.Clear;
test := random(49);
end;
end;
Edit1.Text := 'Generating ' + Inttostr(i) + ' of 49 done';
Memo1.Lines.Add(Inttostr(test));
end;
hier kommen trotzdem noch Nullen mit rein und manchmal kommen nur 2 zahlen..ich versteh das nicht.

weiterhin hab ich noch ne frage:
ich hab ein onclick ereignis, und will in einem anderen onclick ereignis darauf "zugreifen"
dh ich klick auf nen button, dann prozedur usw und dann will ich button2 sagen
if button1.click then begin
// meine code
end;

aber jedes mal kommt ne fehlermeldung, habs schon anders versucht, geht auch nicht.

Ich sag schon mal danke für die Hilfe

guidok 2. Nov 2009 14:22

Re: randomize problem
 
Zunächst mal: Es gibt keine if-Schleifen :zwinker:

Das Problem mit der Null kannt du am einfachsten so lösen:

Delphi-Quellcode:
test := random(48) + 1;
Damit werden Zahlen zwischen 1 und 49 erzeugt.

Dir ist schon klar, dass du mit der Anweisung "memo1.clear" den kompletten Inhalt des Memos löscht, inklusive der Zahlen, die korrekt gezogen wurden?

Um zu verhindern, dass Zahlen doppelt kommen könntest musst du die bereits gezogenen Zahlen irgendwo speichern und nach dem Ziehen einer neuen Zahl prüfen, ob diese bereits vorhanden ist. In diesem Fall einfach noch eine neue Zahl ziehen.

Zitat:

weiterhin hab ich noch ne frage
Dafür solltest du bitte ein neues Thema eröffnen.

ToFaceTeKilla 2. Nov 2009 14:23

Re: randomize problem
 
Hiho, erstmal Willkommen in der DP!

Wegen der Null, mach einfach
Delphi-Quellcode:
random(49)+1
Edit: Narf, wo war der Rote wieder? oO

Nersgatt 2. Nov 2009 14:23

Re: randomize problem
 
Ich rücke Dir den Code mal etwas sinnvoller ein, evtl. siehst Du Deinen Fehler dann selbst:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  randomize;

  for i := 1 to 6 do begin
    test := random(49);

  if test = 0 then begin
    memo1.clear;
    test := random(49);

    if test < 6 then begin
      memo1.Clear;
      test := random(49);
    end;

  end;

  Edit1.Text := 'Generating ' + Inttostr(i) + ' of 49 done';
  Memo1.Lines.Add(Inttostr(test));
end;

Luckie 2. Nov 2009 14:27

Re: randomize problem
 
Und Delphi-Referenz durchsuchenRandomize bitte nur einmal beim Start des Programms aufrufen.

himitsu 2. Nov 2009 14:32

Re: randomize problem
 
random(49) + 1 = 1 bis 49

Zitat:

Zitat von Nersgatt
Ich rücke Dir den Code mal etwas sinnvoller ein, evtl. siehst Du Deinen Fehler dann selbst:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  randomize;

  for i := 1 to 6 do begin
    test := random(49);

    if test = 0 then begin
      memo1.clear;
      test := random(49);

      if test < 6 then begin
        memo1.Clear;
        test := random(49); <<<<<<<<
      end;

    end;

    Edit1.Text := 'Generating ' + Inttostr(i) + ' of 49 done';
    Memo1.Lines.Add(Inttostr(test));
  end;
end; // fehlte, aber egal

da fehlte zwar 'noch 'ne ebene, aber was Nersgatt sagen wollte.
wenn z.B. an der markieren Stelle eine 0 erzeugt wird ... was passiert dann wohl?

sirius 2. Nov 2009 14:33

Re: randomize problem
 
Zitat:

Zitat von ToFaceTeKilla
Wegen der Null, mach einfach
Delphi-Quellcode:
random(48)+1
Edit: Narf, wo war der Rote wieder? oO

Zwei User, und zweimal dieselbe (falsche) Lösung? :gruebel:
Delphi-Quellcode:
random(49)+1;
liefert doch die richtige Lösung.

guidok 2. Nov 2009 14:35

Re: randomize problem
 
Zitat:

Zitat von sirius
Zwei User, und zweimal dieselbe (falsche) Lösung? :gruebel:

Mist, nicht aufgepasst, aber dafür haben wir ja dich :thumb:

ToFaceTeKilla 2. Nov 2009 14:40

Re: randomize problem
 
Ist doch richtig, weis gar nicht was du hast :stupid:

himitsu 2. Nov 2009 14:45

Re: randomize problem
 
macht nix ... ihr hatte zumindestens die ursprüngliche Rechnung beibehalten
random(49) und dann die 0 ignorieren macht Max(Random(49), RandomRange(1, 49))
und dieses entspricht random(48)+1 *tröst*

Aber bei "6 aus 49" aka "6 mal 1..49" ist eigentlich:
random(49) = 0..48
random(49) + 1 = 1..49


PS: ansonsten ist das da oben aber "6 * 1 aus 49" und nicht "6 aus 49"
(doppelte Zahlen müssen noch raus)

Wolfgang Mix 2. Nov 2009 14:52

Re: randomize problem
 
@himitsu

Zitat:

random(48) + 1 = 1..49
Ich glaube, Du hast Dich vertppt. Es sollte wohl random(49) + 1 = 1..49 heißen

... und damit ist dann auch die Abfrage auf Null überflüssig

Gruß

Wolfgang

helgew 2. Nov 2009 15:27

Re: randomize problem
 
herrlich, was hier geschieht: es sieht sehr nach copy+paste aus ;-)

Nun dann will ich noch etwas zum Thema beitragen:

Delphi-Quellcode:
Max(random(49), 1)
verzerrt die Verteilung, sprich die Wahrscheinlichkeit von Zahlen kleiner eins wird auf 1.000 übertragen, damit ist die eins häufiger als alle anderen Zahlen. Nicht machen!

fast korrekt ist

Delphi-Quellcode:
 min(round(random*49 + 0.5),49)
Sinn dieses Ansatzes ist es, gleiche Quantilbreiten zu bekommen. Würde man nur round(random*49) machen, so würden die Werte derart auf die integer-Klassen entfallen:

Zitat:

0 .. 0,4999(9) -> "0"
0,5.. 1,4999(9) -> "1"
...
um zu verhindern, dass für die Randquantile nur die halbe Häufigkeit entsteht, wird um 0,5 verschoben. Ebenso könnte man ceil oder floor nehmen, aber ich habe mich erst dieses Wochenende über die schlechte Performance dieser Funktionen unter Delphi7 aufgeregt.

Ich empfehle, eine Histogrammklasse zu implementieren, um die Gleichverteilung zu testen, indem man sie mit sehr vielen Testwerten füttert.

himitsu 2. Nov 2009 16:41

Re: randomize problem
 
@Wolfgang: joar, immer dieses gemeine C&P :oops:

@helgew:
stümmt, aber irgendwie hatte ich es zu sehr "vereinfacht"

Random(49) + 1 = RandomRange(1, 49) = 1 bis 49
und das unter Beibehaltung der "Gleichverteilung"

isilive 2. Nov 2009 16:55

Re: randomize problem
 
@HelgeW: Random(49)+1 ist doch in Ordnung oder?!
Magst du einen Screenie von einem Histogramm posten, wäre mal interessant wie sich die Zahlen wirklich verteilen?!

Und um auf den Rest vom Programm zurückzukommen:

@Painrestricter: schau dir dringend Programmabläufe, if-Abfragen und Schleifen an.
Du wirst eine Schleife brauchen, die so oft eine Zufallszahl erzeugt bis sie nicht mit einer schon gezogenen übereinstimmt. Die Abfrage gegen Null kannst du Dir mit obiger Random-funktion sparen - trotzdem ist es eine gute Übung für bedingte Schleifen.

Und wenn Du dir angewöhnst den Code einzurücken, dann behältst du auch den Überblick besser.

gammatester 2. Nov 2009 17:22

Re: randomize problem
 
Leute, schaut Euch erst mal den Quellcode an: RandomRange(1,49) = random(48)+1. Also gibt es nur Werte 1..48!
---
Delphi-Quellcode:
function RandomRange(const AFrom, ATo: Integer): Integer;
begin
  if AFrom > ATo then
    Result := Random(AFrom - ATo) + ATo
  else
    Result := Random(ATo - AFrom) + AFrom;
end;

himitsu 2. Nov 2009 17:42

Re: randomize problem
 
Dann stimmt aber die Implementierung nicht, denn
OH
RandomRange gibt einen zufälligen Integer-Wert im Bereich von AFrom bis ATo zurück (inklusive)

Wolfgang Mix 2. Nov 2009 17:50

Re: randomize problem
 
Liste der Anhänge anzeigen (Anzahl: 1)
@isilive

Es beantwortet zwar nicht ganz Deine Frage, aber für Integerwerte für 6 aus 49 ist die
Normalverteilung recht gut, was man mit dem angehängten Programm testen kann.

Gruß

Wolfgang

gammatester 2. Nov 2009 18:40

Re: randomize problem
 
Zitat:

Zitat von himitsu
Dann stimmt aber die Implementierung nicht, denn
OH
RandomRange gibt einen zufälligen Integer-Wert im Bereich von AFrom bis ATo zurück (inklusive)

Mag sein, jedenfalls passen Source und Hile nicht zusammen. Aber grottenschlechte Programmierniveaux sind wie ja leider gewöhnt.

Begin OT: Ich erinnere nur an sin(1e20) = 1e20 etc. Den Gipfel an Programmierkunst in Math stellt ev.
Delphi-Quellcode:
function Tanh(const X: Extended): Extended;
begin
  if IsZero(X) then
    Result := 0
  else
    Result := SinH(X) / CosH(X);
end;
dar. Nicht nur daß tanh(1e-20) = 0 ist statt 1e-20, tanh crasht für moderate Argumente statt gegen 1 zu gegehen. Außerdem werden 4(!!) exp-Aufrufe durchgeführt statt nur einem! Tanh war OK in Delpi6, wurde dann offensichtlich verschlimmbessert (von einem Informatik-Erstsemester??).

Aber auch D6 ist saumäßig: Ausgesprochen skandalös ist die völlig falsche Implementation der inversen trigonometrischen Funktionen in D6, Bsp:
Delphi-Quellcode:
function ArcSec(const X: Extended): Extended;
begin
  Result := Cos(1 / X);
end;
statt Result := ArcCos(1 / X);
End OT:

Wolfgang Mix 2. Nov 2009 18:55

Re: randomize problem
 
@gammatester:
ArcSec :?:

gammatester 2. Nov 2009 19:58

Re: randomize problem
 
Zitat:

Zitat von Wolfgang Mix
@gammatester:
ArcSec :?:

Zitat:

Zitat von OH
Calculates the inverse secant of a given number.

Unit

Math

Category

Trigonometry routines

function ArcSec(const X: Extended): Extended;

Description

ArcSec returns the inverse secant of X.


Wolfgang Mix 2. Nov 2009 20:08

Re: randomize problem
 
Naja, dann ist Result ja mehr als Blödsinn

helgew 2. Nov 2009 22:34

Re: randomize problem
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von isilive
@HelgeW: Random(49)+1 ist doch in Ordnung oder?!
Magst du einen Screenie von einem Histogramm posten, wäre mal interessant wie sich die Zahlen wirklich verteilen?!

Visualisierung ist alles... der Mensch braucht den visuellen Input :-)

himitsu 2. Nov 2009 22:57

Re: randomize problem
 
Liste der Anhänge anzeigen (Anzahl: 1)
tja, erst Runden und dann mit +0.5 den Fehler wieder ausmerzen ...
kennt ihr schon Delphi-Referenz durchsuchenTrunc? :mrgreen:

ein bissl dynamischer für noch mehr input
und auch noch Trunc+Random, sowie RandomRange reingemacht


schon schlimm, wie die OH-Beschreibung vom Code abweicht :wall: (RandomRange)

isilive 3. Nov 2009 00:56

Re: randomize problem
 
Gute Arbeit! :mrgreen: So einleuchtend visualisiert hat die Verteilung (der Quantilbreiten, um mit Helge's Worten zu sprechen) sicherlich noch niemand. Da gehen jedem Zweifler die Argumente aus :zwinker:

painrestricter 3. Nov 2009 12:54

Re: randomize problem
 
öh...ja, genau

tut mir leid wenn ich das jetzt so sage, aber ich weiß seit der ersten halben seite nicht mehr wovon ihr redet :?:

aber danke für das (48)+1, jetzt kommt endlich keine null mehr :)

wie ich verhindern kann dass zwei gleiche zahlen vorkommen, weiß ich aber noch nicht.

aber vielen dank jungs! :)

guidok 3. Nov 2009 12:57

Re: randomize problem
 
Zitat:

Zitat von painrestricter
öh...ja, genau

tut mir leid wenn ich das jetzt so sage, aber ich weiß seit der ersten halben seite nicht mehr wovon ihr redet :?:

aber danke für das (48)+1, jetzt kommt endlich keine null mehr :)

wie ich verhindern kann dass zwei gleiche zahlen vorkommen, weiß ich aber noch nicht.

aber vielen dank jungs! :)

Du musst dir merken, welche Zahlen du bereits gezogen hast und falls diese bereits gezogen wurden einfach eine neue ziehen.

Darum ist auch eine for..next-Schleife ungeeignet für dein Problem, weil du ja solange ziehen musst, bis du sechs verschiedene Zahlen hast.

Besser repeat...until oder while...do.

himitsu 3. Nov 2009 13:04

Re: randomize problem
 
so als Tipp () man darf auch sich bei Anderen Tipps holen ... aka Abgucken

Hier im Forum suchenLotto

isilive 3. Nov 2009 13:52

Re: randomize problem
 
Wenn du ein Array für die Zahlen nimmst, kannst du sie der Reihe nach vergleichen.
Das hier ist nur Pseudocode...

Delphi-Quellcode:
array of integer deklarieren
For i := 1 to 6
  repeat
    array[i] = random ...
    flag := true;
    Gib j einen Startwert;
      while j>0 do
        begin
          if array[i] = array[j] then flag := false;
          mache j kleiner;
        end;
  until flag
Offtopic:
Was man ziemlich oft findet sind konstruktionen a'la:
Delphi-Quellcode:
a := random(49);
if a = 0 then
  a := random(49);
weiter ...
was aber nicht verhindert, dass beim zweiten mal die Zahl wieder 0 sein kann... :stupid:

Folgenden Code hab ich mal gefunden:
Delphi-Quellcode:
If CheckBox1.checked Then  // erst wird by ein zufälliger Wert gegeben
  by := RandRange(32, 128)
Else
  by := random(256);

While by = 0 Do            // und dann nochmal verhindert, dass er 0 sein kann.
  If CheckBox1.checked Then
    by := RandRange(32, 128)
  Else
    by := random(256);
Aber wenn es spät in der Nacht schreiben wir alle manchmal so Zeugs, oder? :zwinker:

Wolfgang Mix 3. Nov 2009 16:06

Re: randomize problem
 
Noch eine Idee, war hier schon einmal:

1. Erzeuge eine Liste aller Zahlen im Interval [1;49]
2. Ziehe eine beliebige Zahl aus der Liste, zeige sie an.
3. Lösche(!) nun dieses Element aus der Liste.
4. Führe die Schritte 2..4 insgesamt 6x aus
Fertig. Das ist genau das, was man beim Lotto (z.B.) macht.

oder mein Gedanke:
Erzeuge ein Array of integer von 1..49 und schreibe dort z.B. überall Nullen herein.
Ziehe eine Zahl (z.B 23) und überscchreibe dann Zahl[23} mit der Zufallszahl
Ziehe die nächste Zahl. Wenn es wieder 23 sein sollte, guckst Du im Array bei Zahl[23] nach,
ob sie nicht Null ist. Dann mußt Du halt noch einmal eine Zufallszahl erzeugen
.. usw, bis Du 6 verschiedene Zahlen hast.

Am Ende brauchst Du nicht einmal nach Größe sortieren, sondern im Array nur die Zahlen auslesen,
die nicht den Inhalt Null haben.


PS: Habe den Bug in Post #17 Lotto3.exe beseitigt, hier wurden MaxInt-Werte überschritten.

Gruß

Wolfgang


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:16 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz