Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1836to1840
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Bitte um Bewertung - Uniq Zufallszahl

Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 08:53:22
Konstantin
Guten Morgen zusammen,
ich habe mich mal daran versucht, mit eigenem Hirnschmalz, eine Lösung für sich nicht wiederholende Zufallszahlen zu erstellen.
Es gibt für dieses Unterfagen schon bestehende Lösungen, jedoch wollte ich wie gesagt mal versuchen selbst eine Lösung zu finden.
Jetzt habe ich die Bitte an dieses sehr gute Forum meine Lösung zu bewerten, ob sie wirklich so toll ist. Feier mich da nämlich schon ein bisschen für xD
https://www.herber.de/bbs/user/146891.xlsm
Besten Dank im voraus
Konstantin Nitka
Option Explicit

Public Sub ZUFALLSZAHL()
Dim i As Integer
Dim x As Integer
Dim iRnd As Integer
Dim colSpeicher As New Collection
Dim Eintrag As New clsKlassenmodul
Dim IsUnique As Boolean
Dim iFirstRnd As Integer
Dim iLastRnd As Integer
Dim iMaxEintrag As Integer
Dim wks As Worksheet
Set wks = Tabelle1
Application.ScreenUpdating = False
'Anzahl der Einträge in der Collection
iMaxEintrag = 35
'# Bereich der Zufallszahlen
'Erste Zufallszahl
iFirstRnd = 2
'Letzte Zufallszahl
iLastRnd = 36
'# Zufallszahlen in eine Collection schreiben
'# Vorteil: muss nicht dimensioniert werden
'# Nachteil: langsamer als Array bei vielen Einträgen
'Schleife Starten um Collection zu befüllen.
For i = 1 To iMaxEintrag
'Bei jedem Durchlauf muss eine neues Klassenmodul erstellt werden
'um es als Item in der Collection zu speichern.
Set Eintrag = New clsKlassenmodul
'Sprungmarke
NEUE_ZAHL:
'Zufallszahl generieren lassen.
iRnd = WorksheetFunction.RandBetween(iFirstRnd, iLastRnd)
'Die Erste Zahl direkt in die Collection übernehmen.
If i 

23
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 09:18:29
Tobias
Hallo Konstantin,
ohne mir deine Datei angesehen zu haben:
Warum erstellst du eine Klasse und gibst an die Collection nicht nur den Integer weiter?
Wie wäre es wenn du zuerst Collection mit deinem Zahlbereich füllst und anschließend einfach nur die Werte in zufälliger Reihenfolge aus dieser Collection entnimmst? Es würde das vergleichen ob der Wert schon vorhanden ist entfallen.
Wieso berechnest du iMaxEintrag nicht?
Ansonsten hatte ich schon häufiger Probleme wenn man Worksheets mit Set zuweist und hinterher nicht ordentlich mit

set wks = nothing
die Variablen wieder freigibt.
Dein Code ist allerdings schön verständlich.
Schöne Grüße
Tobias
Anzeige
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 09:37:13
Konstantin
Hey Tobias,
danke schonmal für dein Antwort.

Warum erstellst du eine Klasse und gibst an die Collection nicht nur den Integer weiter?
Im Grunde benötige ich gefühlt ständig Zufallszahlen um irgendwelche wilden Listen zu erstellen.
Die Klasse habe ich aus Gründen der Standardisierung ertsellt.
Somit kann ich immer direkt komplette "Datenpakete zusammenstellen", mit z.B. einer zufälligen Zeilennummer.
Die Klasse besteht meist aus "Name", "Vorname", "Einheit", "Diensttuer", "Zeilennummer" oder ähnlich.

Wie wäre es wenn du zuerst Collection mit deinem Zahlbereich füllst und anschließend einfach nur die Werte in zufälliger Reihenfolge aus dieser Collection entnimmst?
Müsste ich dann nicht auch wieder vergleichen welche Werte ich schon entnommen habe, um dort keine Doppelung zu haben? Wäre doch fast das gleich, nur andersrum.

Wieso berechnest du iMaxEintrag nicht?
iMaxEintrag ist nur hier händisch denifiert. Alle Variablen wie iMaxEintrag, iFirstRnd & iLastRnd können später automatisch gesetzt werden. Daher auch die Variablendeklaration :)

Ansonsten hatte ich schon häufiger Probleme wenn man Worksheets mit Set zuweist und hinterher nicht ordentlich mit
set wks = nothing
die Variablen wieder freigibt.
Das werde ich mir zu Herzen nehmen und umsetzen, da ich was das Freigeben von Variablen angeht vielleicht etwas schlampig bin ^^
Besten Gruß
Konstantin
Anzeige
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 10:05:44
Tobias
Hallo Konstantin,

Wie wäre es wenn du zuerst Collection mit deinem Zahlbereich füllst und anschließend einfach nur die Werte in zufälliger Reihenfolge aus dieser Collection entnimmst?
Müsste ich dann nicht auch wieder vergleichen welche Werte ich schon entnommen habe, um dort keine Doppelung zu haben? Wäre doch fast das gleich, nur andersrum.
Wenn du die entnommene Zahl aus der Collection entfernst kann sie nicht mehr doppelt vorkommen, lediglich deine nächste "Ziehzahl" muss dann im Bereich einsprechend eins kleiner sein.
Schöne Grüße
Tobias
Anzeige
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 10:15:14
Konstantin
Hallo Tobias,
finde den Vorschlag echt gut, steh grad jedoch auf dem Schlauch bei der Umsetzung.
Einträge in zufälliger Reihenfolge aus der Collection lesen und löschen - Verstanden
Den Bereich der zu generierenden Zufallszahl, um den Eintrag aus der Collection zu lesen und löschen, zur Laufzeit einer Schleife dynamisch halten - Unklar
Setze ich das dann wieder mit einer Sprungmarke aus der Schleife heraus um?
Besten Gruß
Konstantin
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 12:49:21
Tobias
Hallo Konstantin,

Private Declare PtrSafe Function GetTickCount Lib "kernel32.dll" () As Long
Sub Zufallszahlen()
Dim iUnten As Integer
Dim iOben As Integer
Dim iRnd As Integer
Dim Werte As New Collection
Dim Ergebnis As String
Dim timer As Long
timer = GetTickCount
iUnten = 2
iOben = 25000
'Collection füllen
For i = iUnten To iOben
Werte.Add i
Next i
'Collection leeren
Do While Werte.Count > 0
iRnd = WorksheetFunction.RandBetween(1, Werte.Count)
Ergebnis = Ergebnis & " | " & Werte(iRnd)
Werte.Remove iRnd
Loop
Debug.Print GetTickCount - timer & " ms Laufzeit"
End Sub
Eventuell am Anfang für 32bit das PtrSafe entfernen!
Ob du nun ein String füllst oder eine andere Collection ist ja dann letztendlich dir überlassen. Ob die Variante mit dem Dictonary besser ist könnte man dann noch testen.
Schöne Grüße
Tobias
Anzeige
Dim timer As Long
01.07.2021 14:45:37
Rudi
Hallo,
würde ich nicht machen.
Timer ist die VBA-Zeitgeberfunktion und gibt die Sekunden seit Mitternacht zurück.

Dim lTimer as Long
wäre OK.
Gruß
Rudi
AW: Dim timer As Long
01.07.2021 15:39:05
Tobias
Hallo Rudi,
das stimmt, hatte die Zeitmessung nur rein Interesse halber noch schnell mit reingemogelt. Die Variable muss definitiv anders benannt werden.
Der Timer war mir nicht mehr eingefallen, damit gehts natürlich auch direkt.

Dim ltimer As Double
ltimer = timer
Debug.Print timer - ltimer & " s Laufzeit"
Schöne Grüße
Tobias
Anzeige
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 10:13:23
Rudi
Hallo,
wenn du ein Dictionary-Objekt statt einer Collection benutzt, kannst du dir die Prüfung auf Existenz sparen.
Gruß
Rudi
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 10:27:50
Konstantin
Hallo Rudi,
auch dir danke für die Zeit und Antwort auf meine Bitte.

wenn du ein Dictionary-Objekt statt einer Collection benutzt, kannst du dir die Prüfung auf Existenz sparen.
Habt direkt mal die Microsoft suche benutzt.
https://docs.microsoft.com/de-de/office/vba/language/reference/user-interface-help/dictionary-object
Es erschließt sich mir nur noch nicht so ganz wie ich hiermit die Prüfung auf Existenz umgehen kann.
Das jedes Element in dem Dictionary einen Uniq-Key bekommt, ok.
Aber wie kann ich dann verhindern das nicht evtl. zwei Einträge mit unterschiedlichem Key den gleichen Wert besitzen?
Auf meine Beispielmappe gemünzt:
Hier weise ich jedem Klassenmodul einen Namen und eine Zeilennummer(Zufallszahl) zu.
Die Zufallszahl nicht doppelt da sonst Einträge überschrieben werden würden.
Dictionary ist da grade ein Böhmisches Dorf für mich -.-
Besten Gruß
Konstantin
Anzeige
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 11:23:22
Konstantin
Hallo Rudi,
Hallo Steuerfuzzi,
habe jetzt mal mit einem Dictionary rumgespielt.
Die Keys vergebe ich mit Zufallszahlen.
Mit Dictionary.Exists(Key) spare ich mir in der Tat eine komplette Prüfschleife :D
Vielen Dank für den Rat.
Besten Gruß
Konstantin
auch gespielt ;-)
01.07.2021 14:32:18
Rudi

Sub Zufall()
Dim oDic As Object, oObj
Dim arrA(), arrB()
Dim i As Integer, iCount As Integer
Const iFirst As Integer = 1  'erste
Const iLast As Integer = 1000  'letzte
iCount = 200                   'Anzahl
Set oDic = CreateObject("scripting.dictionary")
iCount = Application.Min(iCount, iLast - iFirst + 1)
For i = iFirst To iLast
Randomize
oDic(i) = Rnd
Next
ReDim arrA(1 To oDic.Count, 1 To 2)
i = 0
For Each oObj In oDic
i = i + 1
arrA(i, 1) = oDic(oObj)
arrA(i, 2) = oObj
Next oObj
Call QuickSort2(arrA)
ReDim arrB(1 To iCount, 1 To 1)
For i = 1 To iCount
arrB(i, 1) = arrA(i, 2)
Next
Cells(1, 1).Resize(iCount, 1) = arrB
End Sub

Sub QuickSort2(ByRef DasArray, Optional ErsteZeile, Optional LetzteZeile)
On Error Resume Next
Dim UnterGrenze As Long, OberGrenze As Long, aktuelleSpalte As Long
Dim AktuellerWert, GemerkterWert As Variant
If IsMissing(ErsteZeile) Then
ErsteZeile = LBound(DasArray)
End If
If IsMissing(LetzteZeile) Then
LetzteZeile = UBound(DasArray)
End If
UnterGrenze = ErsteZeile
OberGrenze = LetzteZeile
AktuellerWert = DasArray((ErsteZeile + LetzteZeile) / 2, 1)
Do While (UnterGrenze  AktuellerWert And OberGrenze > ErsteZeile)
OberGrenze = OberGrenze - 1
Loop
If (UnterGrenze  ErsteZeile) Then Call QuickSort2(DasArray, ErsteZeile, OberGrenze)
If (UnterGrenze 
Gruß
Rudi
Anzeige
AW: auch gespielt ;-)
01.07.2021 16:14:15
Tobias
Huhu,
gerade mal ausprobiert und die Variante ist deutlich schneller als die Collection!
Aber warum mit dem Dictionary arbeiten wenn du es eh wieder in den Array packst?

Sub Zufall()
Dim arrA()
Dim i As Integer, iCount As Integer
Const iFirst As Integer = 1  'erste
Const iLast As Integer = 25000  'letzte
iCount = 200                   'Anzahl
iCount = Application.Min(iCount, iLast - iFirst + 1)
ReDim arrA(iFirst To iLast, 1 To 2)
For i = iFirst To iLast
arrA(i, 1) = Rnd
arrA(i, 2) = i
Next
Call QuickSort2(arrA)
Cells(1, 1).Resize(iCount, 2) = arrA
Columns(1).Delete
End Sub
Schöne Grüße
Tobias
Anzeige
AW: auch gespielt ;-)
01.07.2021 19:14:31
Rudi

Aber warum mit dem Dictionary arbeiten
weil ich dumm bin ;-)
An sich hatte ich was anderes vor.
schema:
do while oDic.count oDic(worksheetfunction.Randbetween(iFirst,iLast)) = 0
loop
Hatte aber Angst, dass das in einer Ewigkeitsschleife enden könnte.
Gruß
Rudi
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 10:24:52
Der
Hallo,
ich hätte statt einer Collection ein Dictionary genommen. Dort gibt es eine Möglichkeit zu prüfen, ob ein Element bereits existiert. Allerdings erschließt sich mir die Verwendung der Klasse nicht.
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 10:31:04
Konstantin
Hallo Steuerfuzzi,
danke für deine Antwort.
Das Dictionary hat Rudi eben auch schon angesprochen, stehe da grade nur bei der umsetzung der Überprüfung auf dem Schlauch.
Werde später mal Versuche dies zu eruieren, bin da grade limitiert was die Möglichkeite angeht.
Besten Gruß
Konstantin
Anzeige
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 11:23:38
Konstantin
Hallo Rudi,
Hallo Steuerfuzzi,
habe jetzt mal mit einem Dictionary rumgespielt.
Die Keys vergebe ich mit Zufallszahlen.
Mit Dictionary.Exists(Key) spare ich mir in der Tat eine komplette Prüfschleife :D
Vielen Dank für den Rat.
Besten Gruß
Konstantin
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 14:25:06
ede
Hallo Konstantin,
wenn beispielsweise iMaxEintrag 39 wäre, dann läuft da was gegen den Baum. Eine Plausiprüfung wäre angebracht, ob iLastRnd minus iFirstRnd größer iMaxEintrag ist.
Gruss
ede
AW: Ede hat recht
01.07.2021 19:02:52
Sulprobil
Die Sub ist leider nicht gut:
1. Keine Plausi Prüfungen.
2. Es sollte besser eine Funktion sein.
3. Long nehmen an Stelle von Integer.
4. Der Algorithmus ist richtig schlecht, weil sich bereits generierte Zahlen wiederholen können und dann immer wieder neu probiert werden muss. Je näher die Zahl der gewünschten Zufallszahlen an der erlaubten Obergrenze ist, desto potenziert länger läuft das Programm.
Wie kann man das besser machen?
Ich denke, so:
https://berndplumhoff.gitbook.io/sulprobil/excel/excel-vba-solutions/uniqrandint
Dankeschön :)
01.07.2021 23:14:43
Konstantin
Hallo an alle,
habt vielen Dank für die rege Beteiligung und die vielen verschiedenen Lösungsansätze und auch die konstruktive Kritik an meinem Code.
Was nehme ich jetzt mit? Das mein Code wenigstens schön formatiert und gut zu lesen ist ;-)
Nein, Spaß bei Seite.
Grade der Beitrag von Sulrobil, welcher recht nüchtern aber nicht unhöflich formuliert ist, kommt bei mir sehr gut an.
Danke an dieser Stelle für den Link.
Es ist genau das passiert was ich mir erhofft hatte.
Ich kann mit den mir gegeben Antworten etwas anfangen und weiter lernen :)
Nochmals vielen Dank an alle Beteiligten und bis bald.
Besten gruß
Kosta
AW: Bitte um Bewertung - Uniq Zufallszahl
01.07.2021 23:33:27
Yal
Moin Konstantin,
mache es umgekehrt:
eine Collection mit allen Zahlen zwischen iFirst und iLast. Jede Zahl kommt nur einmal vor.
Dann ein Random "x" zwischen 1 und Anzahl von Einträge in der Collection. Da wird ein Zahl "verbraucht": Element "x" aus der Collection wird gelesen und aus der Collection "removed". So kommt er nicht noch einmal vor.
Und so weiter.

Dim C As Collection
Sub Coll_init()
Dim i
Const iFirst = 2
Const iLast = 36
Set C = New Collection
For i = iFirst To iLast
C.Add CStr(i)
Next
End Sub
Sub Verwende()
Dim x
Do While C.Count > 0
x = WorksheetFunction.RandBetween(1, C.Count)
Debug.Print C(x)
C.Remove x
Loop
End Sub
zu bedenken: remove aus einer Collection ist Zeitaufwendig. Coding wird a bissele langsam sein. Bei 40 Einträge kaum merkbar.
VG
Yal
i depp: Tobias hatte diese Lösung schon oT
01.07.2021 23:38:22
Yal

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige