Zufallszahlen


Getting started ... Alles für einen gelungenen Start.

Moderatoren: Jan, Steff

Zufallszahlen

Beitragvon Abapsocke » 17.05.2018, 14:00

Ich möchte Zufallszahlen erstellen und suche dafür eine Möglichkeit in ABAP. Die entsprechenden Funktionsbausteine sind bei mir nicht vorhanden. Daher kann ich sie nicht nutzen.
Zudem brauche ich zahlen im Bereich von 1-100 etwa. (die meisten eher 1-10 oder 1-20)

Wie kann ich das in ABAP bewerkstelligen?
Ich habe im Netz ein paar vorschläge gefunden die sich leider auf die fehlenden Fubas beziehen.
Abapsocke
ForumUser
 
Beiträge: 37
Registriert: 17.04.2018, 15:34
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Sponsor

Alte ABAP-Entwicklerweisheit: Weißt du weder aus noch ein, baust du einen BADI ein

Re: Zufallszahlen

Beitragvon lausek » 17.05.2018, 14:21

Hast du es schon mit cl_abap_random versucht?

Code: Alles auswählen
" min und max müssen nicht zwingend Konstanten sein
  CONSTANTS:
    c_min TYPE i VALUE 1,
    c_max TYPE i VALUE 100.

" Random Generator erzeugen - Uhrzeit als seed, da sonst immer das Gleiche rauskommt!
  DATA(o_random) = cl_abap_random=>create( CONV i( sy-uzeit ) ).

" float( ) gibt eine Gleitkommazahl zwischen 0 und 1 zurück
" Diese Formel ist eine beliebte Programmierübung
  w_num = CONV i( c_min + o_random->float( ) * ( c_max - 1 ) ).
 
lausek
ForumUser
 
Beiträge: 60
Registriert: 23.03.2017, 07:54
Dank erhalten: 19 mal
Ich bin: Student/in

Re: Zufallszahlen

Beitragvon a-dead-trousers » 17.05.2018, 14:26

Klasse CL_ABAP_RANDOM

EDIT: Zu spät :oops:
Theory is when you know something, but it doesn't work.
Practice is when something works, but you don't know why.
Programmers combine theory and practice: Nothing works and they don't know why.

ECC: 6.07
Basis: 7.40
a-dead-trousers
Top Expert
 
Beiträge: 3090
Registriert: 07.02.2011, 13:40
Dank erhalten: 762 mal
Ich bin: Entwickler/in

Re: Zufallszahlen

Beitragvon Abapsocke » 17.05.2018, 14:44

da hängt er sich bei mir an DATA auf.
btw:
Mit Klassen habe ich bei ABAP noch nicht geantwortet. Ist dabei etwas besonders zu beachten?
Abapsocke
ForumUser
 
Beiträge: 37
Registriert: 17.04.2018, 15:34
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re: Zufallszahlen

Beitragvon schick » 17.05.2018, 14:47

Vermutlich hast du ein Release älter 7.4, dann geht die inline Deklaration nicht.

Statt
Code: Alles auswählen
DATA(o_random) = cl_abap_random=>create( CONV i( sy-uzeit ) ).


müsstest du dann mit
Code: Alles auswählen
o_random = cl_abap_random=>create( CONV i( sy-uzeit ) ).

arbeiten und das Feld o_random vorher mit DATA deklarieren.
schick
ForumUser
 
Beiträge: 19
Registriert: 16.02.2018, 08:22
Dank erhalten: 2 mal
Ich bin: Berater/in

Beitragvon lausek » 17.05.2018, 14:52

Ich kann mir nichts vorstellen was an Klassen besonders sein soll. Darauf kommen wir dann zurück wenn du ein spezifisches Problem hast ^^


Das wäre jetzt auch kompatibel zu älteren Versionen:
Code: Alles auswählen
  DATA:
        o_random TYPE REF TO cl_abap_random,
        w_num    TYPE i.

  w_num = sy-uzeit.
  o_random = cl_abap_random=>create( w_num ).

"...
  w_num = c_min + o_random->FLOAT( ) * ( c_max - 1 ).
 
lausek
ForumUser
 
Beiträge: 60
Registriert: 23.03.2017, 07:54
Dank erhalten: 19 mal
Ich bin: Student/in

Re: Zufallszahlen

Beitragvon Abapsocke » 17.05.2018, 14:54

als was müsste in dem Fall das Feld o_random deklariert werden.

Ich habe jetzt einfach mal Type sy-uzeit verwendet.

Nun bekomme ich den Fehler :
Abapsocke
ForumUser
 
Beiträge: 37
Registriert: 17.04.2018, 15:34
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re:

Beitragvon Abapsocke » 17.05.2018, 14:57

lausek hat geschrieben:Ich kann mir nichts vorstellen was an Klassen besonders sein soll. Darauf kommen wir dann zurück wenn du ein spezifisches Problem hast ^^


Das wäre jetzt auch kompatibel zu älteren Versionen:
Code: Alles auswählen
  DATA:
        o_random TYPE REF TO cl_abap_random,
        w_num    TYPE i.

  w_num = sy-uzeit.
  o_random = cl_abap_random=>create( w_num ).

"...
  w_num = c_min + o_random->FLOAT( ) * ( c_max - 1 ).
 



das wars, danke.
Abapsocke
ForumUser
 
Beiträge: 37
Registriert: 17.04.2018, 15:34
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re: Zufallszahlen

Beitragvon black_adept » 17.05.2018, 15:22

Aber warum verwendest du CL_ABAP_RANDOM->FLOAT wenn du scheinbar eine zufällige Integerzahl haben willst? Dafür gibt es doch CL_ABAP_RANDOM_INT oder die Methode INTINRANGE in der Klasse CL_ABAP_RANDOM
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 3101
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 526 mal
Ich bin: Freiberufler/in

Re: Zufallszahlen

Beitragvon black_adept » 17.05.2018, 15:40

Und noch ein Nachtrag: Wenn das eine Programmierübung sein sollte um gleichmäßig verteilte Zahlen von c_min bis c_max zu erhalten stimmt das auch nicht, falls zwischen c_min und c_max noch weitere Zahlen liegen.
Wenn c_min z.B. 1 ist und c_max 10 ist dann sollten ja eigentlich alle Zahlen von 1-10 ca gleich oft auftauchen - aber bei deiner Implementierung bekommen die Zahlen 1 und 10 jeweils 1/18 aller Zahlen und die Zahlen 2-9 jeweils 1/9.
Einfach mal einen Loop bauen und das System zählen lassen....
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 3101
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 526 mal
Ich bin: Freiberufler/in

Re: Zufallszahlen

Beitragvon Abapsocke » 22.05.2018, 09:22

Was ist denn der Unterschied zwischen FLOAT und INT? Wenn ich richtig liege, dann ist Float für Zahlen mit Fließkommastelle, also tatsächlich in meiner derzeitigen Anfrage, wo ich ganze Zahlen brauche erstmal nicht so wichtig. Tatsächlich brauche ich aber zumindest Kommazahlen (auch wenn diese am Ende wieder gerundet werden) im Verlauf meiner Arbeit.

Was den zweiten Nachtrag betrifft: ja, ich brauche letztendlich Zahlen, so als würde ich sie auswürfeln. Klar wäre ein System gut, bei dem letztendlich alle Zahlen gleich häufig auftreten. Für meine Übungszwecke ist es nicht ganz so wichtig, da ich weiß das man im Bereich von Zufallsgeneratoren da noch mit ganz anderen Mitteln arbeiten kann. Wenn es dafür aber eine einfache Lösung gibt, dann interessiert mich das natürlich sehr.

Konkret geht es hier um eine Übung bei der ich alle Einzelthemen die ich über ABAP gelernt habe zusammen fasse und anwende. Dies mache ich in der Form eines Spiels, das relativ simpel aufgebaut ist, bei dem ich aber alle gelernten Dinge abhaken kann.

Was ist der Unterschied der verschiedenen genannten Methoden?
Abapsocke
ForumUser
 
Beiträge: 37
Registriert: 17.04.2018, 15:34
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re: Zufallszahlen

Beitragvon black_adept » 22.05.2018, 10:38

Abapsocke hat geschrieben:Tatsächlich brauche ich aber zumindest Kommazahlen (auch wenn diese am Ende wieder gerundet werden) im Verlauf meiner Arbeit.
Warum?
Abapsocke hat geschrieben:Was den zweiten Nachtrag betrifft: ja, ich brauche letztendlich Zahlen, so als würde ich sie auswürfeln. Klar wäre ein System gut, bei dem letztendlich alle Zahlen gleich häufig auftreten [...] Wenn es dafür aber eine einfache Lösung gibt, dann interessiert mich das natürlich sehr.
Dafür gibt es CL_ABAP_RANDOM_INT oder die Methode INTINRANGE in der Klasse CL_ABAP_RANDOM ( déjà vu )
Abapsocke hat geschrieben: da ich weiß das man im Bereich von Zufallsgeneratoren da noch mit ganz anderen Mitteln arbeiten kann.
Soso - was genau weißt du denn da bzw. was sind das für Mittel - das würde mich gerade mal stark interessieren.
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 3101
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 526 mal
Ich bin: Freiberufler/in

Re: Zufallszahlen

Beitragvon DeathAndPain » 23.05.2018, 12:24

Ich würde da einfach einen GET TIME machen und dann die hintersten Stellen als Zufallsziffern missbrauchen. Oder zu Programmbeginn einen GET RUN TIME und dann später wieder einen, wenn man wieder eine Zufallszahl braucht. Solange zwischen den beiden GET RUN TIMEs mindestens eine Benutzeraktion liegt (so dass das System auf eine Eingabe wartet), hat man da im Milli- und Mikrosekundenbereich perfekte Zufallszahlen. Teilweise auch ohne Benutzeraktion, einfach mit irgendeinem Datenbankzugriff... es ist mir nicht gelungen, experimentell zu ergründen, ob ein JOIN, eine inhaltliche Subquery oder eine EXISTS-Subquery am performantesten ist, weil die Laufzeiten auch abgesehen vom Caching derart drastisch streuen (mehrere 100%), dass die einzelne Laufzeit als komplett zufällig angesehen werden muss - gerade im Bereich der hinteren Stellen. Auf solch SAP-Server ist halt immer eine Menge los, vor allem wenn er, wie heutzutage üblich, auf einer virtuellen Maschine läuft und sich die Hardware mit soundsoviel anderen teilt.

Testcode war:

Code: Alles auswählen
*&---------------------------------------------------------------------*
*& Report ZTEST_TABLE_SEARCH
*&---------------------------------------------------------------------*
REPORT ZTEST_TABLE_SEARCH2.

DATA: T_OBJID TYPE STANDARD TABLE OF HROBJID WITH HEADER LINE,
      I TYPE I,
      J TYPE I,
      RUNTIME TYPE I.

SELECTION-SCREEN COMMENT 1(83) TEXT-COM.

PARAMETERS: JN_FIRST RADIOBUTTON GROUP ONE,
            SB_FIRST RADIOBUTTON GROUP ONE,
            EX_FIRST RADIOBUTTON GROUP ONE.

*** START-OF-SELECTION ***
START-OF-SELECTION.

  CASE 'X'.
    WHEN JN_FIRST.
      PERFORM SELECT_WITH_JOIN.
      WRITE: / 'Join:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_SUBQUERY.
      WRITE: / 'Subquery:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_EXISTS.
      WRITE: / 'Exists-Clause:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
    WHEN SB_FIRST.
      PERFORM SELECT_WITH_SUBQUERY.
      WRITE: / 'Subquery:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_JOIN.
      WRITE: / 'Join:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_EXISTS.
      WRITE: / 'Exists-Clause:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
    WHEN EX_FIRST.
      PERFORM SELECT_WITH_EXISTS.
      WRITE: / 'Exists-Clause:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_SUBQUERY.
      WRITE: / 'Subquery:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
      PERFORM SELECT_WITH_JOIN.
      WRITE: / 'Join:', RUNTIME, 'microseconds'.
      WRITE: / LINES( T_OBJID ), 'table entries'.
  ENDCASE.

*&---------------------------------------------------------------------*
*&      Form  SELECT_WITH_JOIN
*&---------------------------------------------------------------------*
FORM SELECT_WITH_JOIN.
  GET RUN TIME FIELD I.
  SELECT OBJID INTO TABLE T_OBJID FROM PA0001
    JOIN HRP1001 ON HRP1001~SOBID = PA0001~PERNR
   WHERE PA0001~WERKS = 'Z001'
     AND PA0001~BEGDA <= SY-DATUM
     AND PA0001~ENDDA >= SY-DATUM.
  GET RUN TIME FIELD J.
  RUNTIME = J - I.
ENDFORM.

*&amp;---------------------------------------------------------------------*
*&amp;      Form  SELECT_WITH_SUBQUERY
*&amp;---------------------------------------------------------------------*
FORM SELECT_WITH_SUBQUERY.
  GET RUN TIME FIELD I.
  SELECT OBJID INTO TABLE T_OBJID FROM HRP1001
   WHERE SOBID IN ( SELECT PERNR FROM PA0001
                     WHERE WERKS = 'Z001'
                       AND PA0001~BEGDA <= SY-DATUM
                       AND PA0001~ENDDA >= SY-DATUM ).
  GET RUN TIME FIELD J.
  RUNTIME = J - I.
ENDFORM.

*&amp;---------------------------------------------------------------------*
*&amp;      Form  SELECT_WITH_EXISTS
*&amp;---------------------------------------------------------------------*
FORM SELECT_WITH_EXISTS.
  GET RUN TIME FIELD I.
  SELECT OBJID INTO TABLE T_OBJID FROM HRP1001
   WHERE EXISTS ( SELECT PERNR FROM PA0001
                     WHERE PERNR = HRP1001~SOBID
                       AND WERKS = 'Z001'
                       AND PA0001~BEGDA <= SY-DATUM
                       AND PA0001~ENDDA >= SY-DATUM ).
  GET RUN TIME FIELD J.
  RUNTIME = J - I.
ENDFORM.
DeathAndPain
Expert
 
Beiträge: 814
Registriert: 05.05.2006, 10:14
Dank erhalten: 189 mal
Ich bin: Entwickler/in

Re: Zufallszahlen

Beitragvon black_adept » 23.05.2018, 16:23

DeathAndPain hat geschrieben: hat man da im Milli- und Mikrosekundenbereich perfekte Zufallszahlen
Ich hoffe du hast jetzt auch einen Beleg für diese Aussage und dass diese Zahlen tatsächlich besser zufallsverteilt sind als die Random-Klassen und auch dass man damit gut Zufallszahlen im Bereich zwischen 1 und 1.000.000 erzeugen kann
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de
black_adept
Top Expert
 
Beiträge: 3101
Registriert: 08.01.2003, 13:33
Wohnort: Lehrte ( bei Hannover )
Dank erhalten: 526 mal
Ich bin: Freiberufler/in

Re: Zufallszahlen

Beitragvon DeathAndPain » 24.05.2018, 10:48

Ich weiß nicht, wie gut die Random-Klassen arbeiten, wohl aber, dass es keinen bekannten mathematischen Algorithmus gibt, der perfekte Zufallszahlen (die den Gesetzen der Stochastik vollständig standhalten) erzeugen kann. Die Uhrzeit hingegen ist ein ebenso zufälliger Wert, wie wenn man einen Würfel wirft. Natürlich nicht, wenn zwischen zwei Abgriffzeitpunktenin etwa eine konstante Rechenzeit liegt. Wenn wir aber Rechenzeiten haben, die wie bei meinen Tests wild zwischen 85.641 und 517.211 schwanken, dann wird man bei den ersten Stellen sicherlich noch rechenzeitabhängige Einflüsse wahrnehmen können. Die hinteren Stellen sidn dann aber rein zufällig, da sie von der tatsächlichen Rechenzeit nicht abhängig sind.

Zugegebenermaßen erhält man damit nur 3-4 verwendbare Stellen, da die Rechenzeit insgesamt zu kurz ist, um noch mehr völlig umstandsunabhängige Stellen zu erzeugen. Ggf. müsste man etwas machen, was mehr Rechenzeit in Anspruch nimmt (da reichen wenige Sekunden, um alle Stellen im Milli- und Mikrosekundenbereich nutzen zu können.

Hat man eine Benutzerinteraktion dazwischen, also etwas, bei dem SAP auf eine Benutzereingabe wartet, dann hat man sowieso gewonnen, denn wann der Benutzer da Enter drückt, ist hinsichtlich der Milli- und Mikrosekundenwerte völlig zufällig.
DeathAndPain
Expert
 
Beiträge: 814
Registriert: 05.05.2006, 10:14
Dank erhalten: 189 mal
Ich bin: Entwickler/in

Nächste

Zurück zu ABAP® für Anfänger

  Aktuelle Beiträge   
s4hana-cloud
vor 22 Minuten von sap_inchen 1 Antw.
500 Internal Server Error
vor 8 Stunden von zzcpak 1 Antw.
Dokumentinformationen lesen vom DVS
vor 10 Stunden von Tron 4 Antw.
Tabs innerhalb von Tabs
vor 11 Stunden von ewx 4 Antw.
Fakturierungsplan in Kontrakten ändern
vor 7 Stunden von DeathAndPain 1 Antw.

  Ähnliche Beiträge beta
Keine Beiträge gefunden - versuche es mit der erweiterten Suche.

 

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder