Hallo, Michael,
Dein Code verursacht zwei Typkonvertierungs-Notes:
1. Numeric to character Das passiert in der Definition von FINDME. Hier wird das Character-Informat $20. auf die numerische Variable N angewandt. Passender wäre hier ein PUT-Statement mit einem numerischen Format. Vorschlag: findme = PUT(n, 11.-l); (Das -l sorgt für Linksbündigkeit, was im weiteren Verlauf wichtig wird, falls START_NUMBER nicht schon 11-stellig ist.)
2. Character to numeric Das passiert an drei Stellen: a) Die SUBSTR-Funktion liefert ein Character-Ergebnis, das in einer numerischen Addition verwendet wird.
Abhilfe: quersumme = quersumme + input(substr(findme,i,1), 1.); b) SAS ist schon kulant, dass es die Anwendung des numerischen Formats 20. auf die Character-Variable FINDLAG kommentarlos akzeptiert. Die PUT-Funktion liefert aber ein Character-Ergebnis, zu dem dann die Zahl 1 addiert wird. Vorschlag: s. u. c) Bei PUT(findme,20.) greift wieder die Kulanz, aber der Vergleich des resultierenden Strings mit dem zuvor in eine Zahl umgewandelten Wert (PUT(findlag,20.) + 1) erfordert dann doch die Konvertierung des Strings in eine Zahl.
Vorschlag für Punkte b und c: IF INPUT(findlag,11.) + 1 EQ INPUT(findme,11.) THEN DO;
Im Sinne eines ganz "sauberen" Logs wäre es noch schön, die Note "Missing values were generated ..." zu eliminieren. Die kommt zustande, weil der erste Wert, den FINDLAG von der LAG-Funktion erhält, ein Leerzeichen ist, zu dem nach Umwandlung in ein numerisches Missing die Zahl 1 addiert wird.
Daher modifizierter Vorschlag für 2.b und c: IF SUM(INPUT(findlag,11.),1) EQ INPUT(findme,11.) THEN DO;
Die Laufzeit verlängert sich allerdings durch die Verschönerungen ein wenig (insg. um ca. 1 - 3 %?).
Zur Frage nach meinem Code: Das INIT ist nur eine numerische Variable, die ich so genannt habe, weil sie als "Flag" dafür dient, ob die betreffende Codezeile schon einmal ausgeführt wurde. Ist dies noch nicht geschehen, ist die Variable noch nicht initialisiert, also missing. Die Bedingung ~init (also NOT init) ist dann erfüllt und die Schleifenvariablen werden von 0 auf die zu Testzwecken gewünschten Startwerte hochgesetzt. Da INIT sodann auf 1 initialisiert wird, ist ~init im weiteren Verlauf nie wieder erfüllt.
Was Laufzeitmessungen angeht, hätte ich eigentlich auf die (FULL)STIMER-Angaben vertraut. Hast Du schon unglaubwürdige Zeitangaben beobachtet? Alternativ (insb. wenn die Gesamtlaufzeit mehrerer Steps interessiert) kann man freilich auch vor und nach dem betreffenden Programmteil mit %put %sysfunc(datetime(), datetime.); Timestamps ins Log schreiben oder mit wenig mehr Aufwand sogar die Zeitdifferenz zwischen den beiden Timestamps ausrechnen lassen.
@HeideTribius: Den Performance-Test kann ich gern auf meinem Rechner laufen lassen, aber überzeugender fände ich es, wenn die Laufzeiten nicht von einem der teilnehmenden "Läufer" selbst gemessen würden.
Viele Grüße
Reinhard
... View more