PDA

View Full Version : Grenze für Zufallszahlenerzeugung



Seiten : [1] 2

BRoemer
02-10-23, 13:14
Wir nutzen folgendes Statement zur Erzeugung einer Zufallszahl:
Exec SQL Set :ZufallsZ2 = Rand();
wobei ZuFallsZ2 als 15,7 Feld definiert ist.
Man denkt es würden maximal 9999999 verschiedene Zahlen erzeugt werden, tatsächlich sind es auch bei 9999999 Durchläufen nur 32766 verschiedene Zahlen.
Wo ist der Denkfehler/Programmfehler?

Die Zufallszahl wird als Index eines Lagerplatzes genutzt.

dschroeder
02-10-23, 14:44
Ich weiß nicht, ob meine Antwort das Problem löst, aber:

Rand() liefert keine Zahl, die größer als 1 ist. Es wird immer nur eine Zahl (Genauigkeit double float) zwischen 0 und 1 geliefert. Um daraus eine für dich brauchbare Zufallszahl zu bekommen, musst du die Zahl mit deinem maximalen Wertebereich multiplizieren.

Z.B.: Du willst einen Würfelwurf abbilden:

Dann wäre deine Zufallszahl int(Rand() * 6) + 1.

Wenn du deine 9.999.999 Millionen Lagerplätze abbilden wolltest, müsstest du int(Rand() * 9999999 ) + 1 verwenden. Das "+ 1" ist dafür, dass du keine 0 erhältst und dass dein maximaler Wert auch erreicht wird.

Dein Ergebnisfeld sollte in deinem Fall übrigens ganzzahlig sein!

Also Zufallszahl nicht als 15,7 sondern als 8,0 deklarieren!

Dieter

BRoemer
02-10-23, 16:58
EXEC SQL SET :ZZAHL = (int(Rand() * 9999999 ) + 1); wobei ZZAHL 7,0
Es werden 32767 verschiedene Zahlen produziert.
Wir haben das Programm 2mal durchlaufen lassen. Die Zahlen sind identisch.

dschroeder
02-10-23, 17:32
Sorry, mein Beispielprogramm, das hier eben noch stand war Quatsch. Ich lösche den Code aus diesem Text.

dschroeder
02-10-23, 17:43
Du hast Recht. Mein Beispielprogramm kommt auch immer nur auf ca. 32000 unterschiedliche Zahlen.




dcl-s zahlen packed(8) dim(100000);
dcl-s zahl packed(8);
dcl-s elem packed(8);
dcl-s i packed(8);

clear zahlen;

for i=1 to 200000;

exec sql set :zahl = (int(Rand() * 9999999 ) + 1);
if %lookup(zahl : zahlen) = 0;
elem += 1;
zahlen(elem) = zahl;
endif;

endfor;

dsply %char(elem);

*inlr = *on

dschroeder
02-10-23, 18:03
Ich habe es eben mal mit SQL probiert. Dabei kommen tatsächlich nur 32768 unterschiedliche Zahlen raus. Obwohl die Nachkommastellen von Rank() sehr zahlreich sind, sind viele Daten gleich.

Hier mein Test (mit eine Tabelle, die mehr als 3,7 Millionen Datensätze enthält:

-- Aus folgender Abfrage kommt immer 32768 raus:
with daten as (
select rand() as zahl from mytable limit 1000000)
select count(distinct zahl) from daten
;

-- Hier mal ein paar Beispieldaten aus folgender Abfrage:
with daten as (
select rand() as zahl from mytable limit 1000000)
select zahl from daten order by zahl
;
0.00924710837122715
0.00924710837122715
0.00924710837122715
0.009277626880703146
0.009277626880703146
0.009277626880703146
0.009277626880703146
0.009277626880703146
0.009277626880703146


Da müsste man IBM mal fragen, was das soll.

prsbrc
03-10-23, 12:42
So ganz Random sind die Zahlen wohl nicht.
Was spircht gegen die RRN als Index?

Fuerchau
03-10-23, 15:34
Zufallszahl als Index für eine Lagerplatz?
Da finde ich persönlich eine Identity-Column als INT oder BIGINT, die sich ständig hochzählt, für geeigneter.
Neben der Anforderung eigentlich eine Platz-Id zu haben á la 'Lager-Gang-Regal-Block-Ebene-Platz'.
Zufall sollte in der Logistik eher nicht vorkommen;-).

Edefauler
04-10-23, 08:10
Zufall sollte in der Logistik eher nicht vorkommen;-).

https://www.zufall.de/

...sorry- konnte ich mir nicht verkneifen ;-)

BenderD
04-10-23, 10:45
... habe mal auf die Schnelle ein create table as (select rand() unrand from aLargeTable) with data gemacht. Mit analogen Resultaten. Da sind alle Faktoren raus, über die man nachdenken könnte.

=> die Funlktion rand() ist in DB2/400 völliger Murks!

Wie das für Lagerplätze funzen soll, ierschließt sich mir allerdings nicht. Selbst eine korrekte rand() Funktion ist nicht frei von Kollisionen und wo soll dann der Kram hin?

D*B