Saturday 11 November 2017

Perl Moving Average Funktion


Dieses Kapitel stellt Ihnen die Konzepte hinter Referenzen zu Perl-Modulen, Paketen und Klassen vor. Es zeigt auch, wie man ein paar Beispielmodule erstellt. Ein Perl-Modul ist ein Satz von Perl-Code, der wie eine Bibliothek von Funktionsaufrufen wirkt. Der Begriff Modul in Perl ist gleichbedeutend mit dem Wortpaket. Pakete sind ein Merkmal von Perl 4, während Module in Perl 5 vorherrschen. Sie können alle Ihre wiederverwendbaren Perl-Code für eine Reihe von Aufgaben in einem Perl-Modul zu halten. Daher ist die gesamte Funktionalität, die sich auf eine Art von Aufgabe bezieht, in einer Datei enthalten. Es ist einfacher, eine Anwendung auf diesen modularen Blöcken zu bauen. Daher wendet sich das Wortmodul etwas mehr als das Paket an. Heres eine kurze Einführung in Module. Bestimmte Themen in diesem Abschnitt werden im Laufe des Buches detailliert behandelt. Lesen Sie die folgenden Absätze sorgfältig durch, um einen Überblick darüber zu erhalten, was bei Ihnen steht, wenn Sie schreiben und Ihre eigenen Module verwenden. Was verwirrend ist, ist, dass die Begriffe Modul und Paket in allen Perl-Dokumentationen austauschbar verwendet werden, und diese beiden Begriffe bedeuten dasselbe. Also beim Lesen Perl Dokumente, nur denken, quotpackagequot, wenn Sie sehen, quotmodulequot und umgekehrt. Also, was ist die Voraussetzung für die Verwendung von Modulen Nun, Module sind da zu verpacken (verzeihen Sie die Wortspiele) Variablen, Symbole und zusammenhängende Datenelemente zusammen. Zum Beispiel mit globalen Variablen mit sehr häufigen Namen wie k. J Oder ich in einem Programm ist in der Regel keine gute Idee. Auch ein Loop-Zähler, i. Sollte in zwei verschiedenen Teilen des Codes selbständig arbeiten dürfen. Wenn du i als globale Variable deklarierst und dann in einer Unterroutine inkrementierst, schaffe es unüberschaubare Probleme mit deinem Anwendungscode, weil die Subroutine aus einer Schleife aufgerufen worden sein kann, die auch eine Variable namens i verwendet. Die Verwendung von Modulen in Perl ermöglicht es, Variablen mit demselben Namen an verschiedenen, verschiedenen Stellen im selben Programm zu erstellen. Die für Ihre Variablen definierten Symbole werden in einem assoziativen Array gespeichert, das als Symboltabelle bezeichnet wird. Diese Symboltabellen sind für ein Paket einzigartig. Daher können Variablen mit demselben Namen in zwei verschiedenen Paketen unterschiedliche Werte haben. Jedes Modul hat eine eigene Symboltabelle aller Symbole, die in ihm deklariert sind. Die Symboltabelle isoliert grundsätzlich auch Namen in einem Modul von einem anderen. Die Symboltabelle definiert einen Namespace. Das heißt, ein Raum für unabhängige Variablennamen existieren in. So verhindert die Verwendung von Modulen mit jeweils einer eigenen Symboltabelle, dass eine Variable, die in einem Abschnitt deklariert ist, die Werte anderer Variablen mit demselben Namen, die an anderer Stelle in derselben angegeben sind, überschreibt Programm. Tatsächlich gehören alle Variablen in Perl zu einem Paket. Die Variablen in einem Perl-Programm gehören zum Hauptpaket. Alle anderen Pakete innerhalb eines Perl-Programms sind entweder in diesem Hauptpaket verschachtelt oder auf derselben Ebene vorhanden. Es gibt einige wirklich globale Variablen, wie das Signalhandler-Array SIG. Die allen anderen Modulen in einem Applikationsprogramm zur Verfügung stehen und nicht über Namespaces isoliert werden können. Nur die variablen Bezeichner, die mit Buchstaben oder Unterstrich beginnen, werden in einer Modul-Symboltabelle gehalten. Alle anderen Symbole, wie die Namen STDIN. STDOUT. STDERR. ARGV ARGVOUT. ENV Inc. Und SIG sind gezwungen, im Paket main zu sein. Das Umschalten zwischen den Paketen betrifft nur Namespaces. Alles, was Sie tun, wenn Sie ein Paket oder ein anderes verwenden, erklärt, welche Symboltabelle als Standard-Symboltabelle für die Suche nach Variablennamen verwendet wird. Nur dynamische Variablen werden durch die Verwendung von Symboltabellen beeinflusst. Variablen, die durch die Verwendung des Schlüsselwortes deklariert wurden, sind immer noch mit dem Codeblock aufgelöst, in dem sie sich befinden, und werden nicht durch Symboltabellen referenziert. Tatsächlich bleibt der Umfang einer Paketdeklaration nur innerhalb des Codeblocks aktiv, in dem es deklariert ist. Wenn Sie also die Symboltabellen mit einem Paket innerhalb einer Unterroutine umschalten, wird die ursprüngliche Symboltabelle, die beim Aufruf des Anrufs wirksam ist, wiederhergestellt Wenn die Subroutine zurückkehrt. Das Umschalten von Symboltabellen wirkt sich nur auf die Standard-Suche von dynamischen Variablennamen aus. Sie können sich immer noch explizit auf Variablen, Dateihandles und so weiter in einem bestimmten Paket verweisen, indem Sie einen Paketnamen voranstellen. Zum Variablennamen. Sie haben gesehen, was ein Paketkontext war, wenn Sie Referenzen in Kapitel 3 verwenden. Ein Paketkontext impliziert einfach die Verwendung der Symboltabelle durch den Perl-Interpreter zum Auflösen von Variablennamen in einem Programm. Durch das Umschalten von Symboltabellen schalten Sie den Paketkontext um. Module können in anderen Modulen verschachtelt werden. Das verschachtelte Modul kann die Variablen und Funktionen des Moduls verwenden, in das es verschachtelt ist. Für verschachtelte Module musst du moduleName verwenden. NestedModuleName und so weiter. Mit dem Doppelkolon (::) geht es auch um mit einem Back-Zitat (). Allerdings ist der Doppelkolon der bevorzugte, zukünftige Weg, um Variablen innerhalb von Modulen zu adressieren. Die explizite Adressierung von Modulvariablen erfolgt immer mit einer vollständigen Referenz. Angenommen, Sie haben ein Modul, Investment. Das ist das Standardpaket im Einsatz, und Sie möchten ein anderes Modul adressieren, Bonds. Die im Investitionsmodul verschachtelt ist. In diesem Fall kannst du Bond nicht benutzen. Stattdessen müssten Sie Investment :: Bond :: verwenden, um Variablen und Funktionen innerhalb des Bond-Moduls zu adressieren. Mit Bond :: würde die Verwendung eines Pakets Bond, das innerhalb des Hauptmoduls und nicht innerhalb des Investment-Moduls verschachtelt ist, implizieren. Die Symboltabelle für ein Modul wird tatsächlich in einem assoziativen Array der Modulnamen gespeichert, die mit zwei Doppelpunkten angehängt sind. Die Symboltabelle für ein Modul namens Bond wird als assoziatives Array Bond :: bezeichnet. Der Name für die Symboltabelle für das Hauptmodul ist main ::. Und kann sogar verkürzt werden auf ::. Ebenso haben alle verschachtelten Pakete ihre Symbole in assoziativen Arrays mit doppelten Doppelpunkten getrennt, die jede Verschachtelungsstufe voneinander trennen. Beispielsweise wird in dem Bond-Modul, das innerhalb des Investment-Moduls verschachtelt ist, das assoziative Array für die Symbole im Bond-Modul als Investment :: Bond :: bezeichnet. Ein Typglob ist wirklich ein globaler Typ für einen Symbolnamen. Sie können Aliasing-Operationen durchführen, indem Sie einem Typglob zuordnen. Ein oder mehrere Einträge in einem assoziativen Array für Symbole werden verwendet, wenn eine Zuordnung über einen Typglob verwendet wird. Der tatsächliche Wert in jedem Eintrag des assoziativen Arrays ist, was Sie beziehen, wenn Sie die VariableName Notation verwenden. So gibt es zwei Möglichkeiten, sich auf Variablennamen in einem Paket zu beziehen: Investment: Geld Investment: Rechnungen Bei der ersten Methode beziehen Sie sich auf die Variablen über eine Typeglob-Referenz. Die Verwendung der Symboltabelle, Investment ::. Ist hier impliziert, und Perl wird die Suche nach Symbolen Geld und Rechnungen zu optimieren. Dies ist die schnellere und bevorzugte Art, ein Symbol zu adressieren. Die zweite Methode verwendet einen Lookup für den Wert einer Variablen, die durch Geld und Rechnungen in dem assoziativen Array für Symbole, Investment :: explizit verwendet wird. Dieser Lookup würde dynamisch durchgeführt und wird nicht von Perl optimiert. Daher wird die Suche gezwungen, das assoziative Array jedes Mal zu überprüfen, wenn die Anweisung ausgeführt wird. Infolgedessen ist die zweite Methode nicht effizient und sollte nur für die Demonstration verwendet werden, wie die Symboltabelle intern implementiert ist. Ein weiteres Beispiel in dieser Aussage kamran husain verursacht Variablen, Unterprogramme und Dateihandles, die über das Symbol kamran benannt werden, um auch über das Symbol husain adressiert zu werden. Das heißt, alle Symboleinträge in der aktuellen Symboltabelle mit dem Schlüssel kamran enthalten nun Verweise auf jene Symbole, die vom Schlüssel husain angesprochen werden. Um eine solche globale Zuordnung zu verhindern, können Sie explizite Referenzen verwenden. Zum Beispiel können Sie mit der folgenden Aussage den Inhalt von husain über die Variable kamran ansprechen. Kamran husain Allerdings werden alle Arrays wie kamran und husain nicht das gleiche sein. Nur was die explizit angegebenen Referenzen geändert werden. Zusammenfassend lässt sich feststellen, wenn Sie einen Typglob einem anderen zuordnen, beeinflussen Sie alle Einträge in einer Symboltabelle unabhängig von der Art der Variablen, auf die verwiesen wird. Wenn Sie eine Referenz von einem Variablentyp zu einem anderen zuordnen, beeinflussen Sie nur einen Eintrag in der Symboltabelle. Eine Perl-Moduldatei hat folgendes Format: Paket Modulname. Modulcode einfügen 1 Der Dateiname muss als ModulName. pm bezeichnet werden. Der Name eines Moduls muss in der Zeichenfolge. pm nach Konvention enden. Die Paketanweisung ist die erste Zeile der Datei. Die letzte Zeile der Datei muss die Zeile mit der 1-Anweisung enthalten. Damit wird mit dem Modul ein wahrer Wert auf das Applikationsprogramm zurückgegeben. Wenn Sie die 1-Anweisung nicht verwenden, wird das Modul nicht korrekt geladen. Die Paketanweisung teilt dem Perl-Interpreter mit, mit einer neuen Namespace-Domain zu beginnen. Grundsätzlich gehören alle Variablen in einem Perl-Skript zu einem Paket namens main. Jede Variable im Hauptpaket kann als mainvariable bezeichnet werden. Heres die Syntax für solche Referenzen: packageNamevariableName Das einfache Zitat () ist gleichbedeutend mit dem Doppelkolon (Operator). Ich decke im nächsten Kapitel mehr Verwendungen des :: Operators ab. Vorläufig müssen Sie sich erinnern, dass die folgenden beiden Anweisungen gleich sind: packageNamevariableName packageName :: variableName Die Double-Colon-Syntax gilt als Standard in der Perl-Welt. Deshalb, um die Lesbarkeit zu bewahren, verwende ich die Doppel-Colon-Syntax im Rest dieses Buches, es sei denn, es ist absolut notwendig, Ausnahmen zu machen, um einen Punkt zu beweisen. Die Standardverwendung eines Variablennamens verweist auf das aktuelle Paket, das zum Zeitpunkt der Kompilierung aktiv ist. Also, wenn Sie im Paket Finance. pm sind und geben Sie eine variable pv. Die Variable ist eigentlich gleich Finance :: pv. Verwenden von Perl-Modulen: use vs. require Sie enthalten Perl-Module in Ihrem Programm, indem Sie die Verwendung oder die require-Anweisung verwenden. Heres den Weg, um eine dieser Aussagen zu verwenden: use ModuleName benötigen ModulName Beachten Sie, dass die. pm-Erweiterung nicht in dem oben gezeigten Code verwendet wird. Beachten Sie auch, dass keine Anweisung erlaubt, dass eine Datei mehr als einmal in ein Programm aufgenommen wird. Der zurückgegebene Wert von true (1) als letzte Anweisung ist erforderlich, um Perl wissen zu lassen, dass ein D-D-D-Modul korrekt geladen und der Perl-Interpreter ignoriert werden kann. Im Allgemeinen ist es besser, die Verwendung Modul-Anweisung zu verwenden, als die Modul-Anweisung in einem Perl-Programm benötigen, um mit zukünftigen Versionen von Perl kompatibel zu bleiben. Für Module, die Sie vielleicht erwägen, die Bedarfserklärung zu verwenden. Heres warum: Die use-Anweisung macht ein bisschen mehr Arbeit als die require-Anweisung, dass sie den Namespace des Moduls ändert, das ein anderes Modul enthält. Sie möchten, dass dieses zusätzliche Update des Namespaces in einem Programm durchgeführt wird. Wenn Sie jedoch Code für ein Modul schreiben, können Sie den Namensraum nicht ändern, es sei denn, es ist explizit erforderlich. In diesem Fall verwenden Sie die Bedarfserklärung. Die Bedarfsanweisung enthält den vollständigen Pfadnamen einer Datei im Inc-Array, so dass sich die Funktionen und Variablen in der Moduldatei während der Ausführungszeit an einem bekannten Ort befinden. Daher werden die Funktionen, die aus einem Modul importiert werden, über eine explizite Modulreferenz zur Laufzeit mit der require-Anweisung importiert. Die use-Anweisung tut dasselbe wie die require-Anweisung, da sie das Inc-Array mit vollständigen Pfadnamen der geladenen Module aktualisiert. Der Code für die use-Funktion geht auch noch einen Schritt weiter und ruft eine Import-Funktion in das Modul, mit dem d die Liste der exportierten Funktionen explizit zur Kompilierzeit geladen wird, wodurch die Zeit für die explizite Auflösung eines Funktionsnamens während der Ausführung gespart wird. Grundsätzlich ist die use-Anweisung gleichbedeutend mit dem ModulName importieren ModuleName Liste der importierten Funktionen Die Verwendung der use-Anweisung ändert Ihren Programm-Namespace, da die importierten Funktionsnamen in die Symboltabelle eingefügt werden. Die Anforderungserklärung ändert nicht Ihren Namespace. Daher ist die folgende Anweisung useNameName () entspricht dieser Anweisung: require ModuleName Funktionen werden aus einem Modul über einen Aufruf einer Funktion namens import importiert. Sie können Ihre eigene Importfunktion in einem Modul schreiben oder das Exporter-Modul verwenden und deren Importfunktion verwenden. In fast allen Fällen werden Sie mit dem Exporter-Modul eine Importfunktion verwenden, anstatt das Rad neu zu erfinden. (Youll erfahren Sie mehr darüber im nächsten Abschnitt.) Sollten Sie sich entscheiden, das Exporter-Modul nicht zu benutzen, müssen Sie in jedem Modul, das Sie schreiben, Ihre eigene Importfunktion schreiben. Es ist viel einfacher, einfach das Exporter-Modul zu benutzen und Perl die Arbeit für dich zu machen. Das Beispiel Letter. pm Modul Der beste Weg, um die Semantik zu veranschaulichen, wie ein Modul in Perl verwendet wird, ist, ein einfaches Modul zu schreiben und zu zeigen, wie man es benutzt. Nehmen wir das Beispiel eines lokalen Darlehens Hai, Rudious Maximus, der einfach müde ist, die gleiche Quittung für paymentquot Buchstaben zu schreiben. Als ein begeisterter Fan von Computern und Perl, Rudious nimmt die faulen Programmierer Ansatz und schreibt ein Perl-Modul, um ihm zu helfen, seine Memos und Briefe zu generieren. Nun, anstatt in Felder in einer Memo-Vorlagendatei einzugeben, muss er nur ein paar Zeilen eingeben, um seine nette, bedrohliche Note zu produzieren. Listing 4.1 zeigt Ihnen, was er eingeben muss. Listing 4.1. Mit dem Letter-Modul. 1 usrbinperl - w 2 3 Uncomment die Zeile unten, um die aktuelle dir in Inc. 4 Push (Inc, pwd) 5 6 verwenden Letter 7 8 Letter :: To ("Rambling Manquot, quotDas Geld für Lucky Dog, Race 2quot) 9 Letter :: ClaimMoneyNice () 10 Letter :: ThankDem () 11 Letter :: Finish () Die use Letter-Anweisung ist vorhanden, um den Perl-Interpreter zu zwingen, den Code für das Modul in das Anwendungsprogramm aufzunehmen. Das Modul sollte sich im Verzeichnis usrlibperl5 befinden, oder Sie können es in jedem Verzeichnis platzieren, das im Inc-Array aufgeführt ist. Das Inc-Array ist die Liste der Verzeichnisse, die der Perl-Interpreter sucht, wenn versucht wird, den Code für das benannte Modul zu laden. Die kommentierte Zeile (Nummer 4) zeigt, wie Sie das aktuelle Arbeitsverzeichnis hinzufügen, um den Pfad einzuschließen. Die nächsten vier Zeilen in der Datei erzeugen den Gegenstand für den Brief. Heres die Ausgabe von der Verwendung des Letter-Moduls: An: Mr. Gambling Man Fm: Rudious Maximus, Loan Shark Dt: Mi Feb 7 10:35:51 CST 1996 Re: Das Geld für Lucky Dog, Race 2 Es ist mir aufmerksam geworden Dass Ihr Konto ist weit über fällig. Du wirst uns bald bezahlen Oder möchtest du, dass ich ovah komme Danke für deine Unterstützung. Die Letter-Modul-Datei wird in Listing 4.2 angezeigt. Der Name des Pakets wird in der ersten Zeile deklariert. Da diese Module Funktionen exportiert werden, verwende ich das Exporter-Modul. Daher ist die Anweisung Exporter erforderlich, um die Funktionalität aus dem Exporter-Modul zu erben. Ein weiterer erforderlicher Schritt ist, das Wort Exports in das ISA-Array zu setzen, um die Suche nach Exported. pm zu ermöglichen. Das ISA-Array ist ein spezielles Array in jedem Paket. Jedes Element im Array listet wo sonst noch eine Methode zu suchen, wenn es nicht im aktuellen Paket gefunden werden kann. Die Reihenfolge, in der Pakete im ISA-Array aufgeführt sind, ist die Reihenfolge, in der Perl nach ungelösten Symbolen sucht. Eine Klasse, die im ISA-Array aufgelistet wird, wird als Basisklasse dieser bestimmten Klasse bezeichnet. Perl cache fehlende Methoden, die in Basisklassen für zukünftige Referenzen gefunden wurden. Das Ändern des ISA-Arrays bündelt den Cache und veranlasst Perl, alle Methoden erneut zu durchsuchen. Lets jetzt schauen Sie sich den Code für Letter. pm in Listing 4.2. Listing 4.2. Das Modul Letter. pm 1 Paket Letter 2 3 erfordern Exporteur 4 ISA (Exporteur) 5 6 head1 NAME 7 8 Letter - Beispielmodul zur Erstellung von Briefkopf für Sie 9 10 head1 SYNOPSIS 11 12 use Letter 13 14 Letter :: Date () 15 Letter :: To (name , Firma, Adresse) 16 17 Dann einer der folgenden: 18 Letter :: ClaimMoneyNice () 19 Letter :: ClaimMoney () 20 Letter :: ThreatBreakLeg () 21 22 Letter :: ThankDem () 23 Letter :: Finish () 24 25 head1 BESCHREIBUNG 26 27 Dieses Modul bietet ein kurzes Beispiel für die Erstellung eines Briefes für einen 28 freundlichen Neighborbood Darlehen Hai. 29 30 Der Code beginnt nach der quotcutquot-Anweisung. 31 schneiden 32 33 EXPORT qw (Datum, 34 an, 35 ClaimMoney, 36 ClaimMoneyNice, 37 ThankDem, 38 Finish) 39 40 41 Drucken heutiges Datum 42 43 Sub Letter :: Datum 44 Datum Datum 45 drucken quotn Heute ist datequot 46 47 48 sub Letter :: To 49 local (name) shift 50 lokal (subject) shift 51 print quotn An: namequot 52 print quotn Fm: Rudious Maximus, Loan Sharkquot 53 print quotn Dt: quot, date 54 print quotn Re: subjectquot 55 drucken quotnnquot 56 Print quotnnquot 57 58 sub Letter :: ClaimMoney () 59 print quotn Du schuldest mir Geld. Holen Sie sich Ihre Handlung zusammenquoten 60 print quotn Wollen Sie, dass ich Bruno zu schicken, um zu drucken. Oder sind Sie gonna pay upquot 62 63 64 sub Letter :: ClaimMoneyNice () 65 print quotn Es ist zu meiner Aufmerksamkeit gekommen, dass Ihr Konto ist 66 Druck quotn Weg über due. quot 67 print quotn Sie gonna bezahlen uns bald..quot 68 Print quotn oder möchtest du, dass ich komme ovahquot 69 70 71 sub Letter :: ThreatBreakLeg () 72 print quotn anscheinend Briefe wie diese dont helpquot 73 print quotn Ich muss ein Beispiel von youquot 74 drucken quotn n sehen Sie im Krankenhaus , Palquot 75 76 77 sub Letter :: ThankDem () 78 print quotnn Vielen Dank für Ihr Supportquot 79 80 81 sub Letter :: Finish () 82 printf quotnnnn Sincerelyquot 83 printf quotn Rudious n 84 84 86 1 Zeilen mit dem Gleichheitszeichen werden verwendet Für die Dokumentation. Sie müssen jedes Modul für Ihre eigene Referenz dokumentieren Perl-Module müssen nicht dokumentiert werden, aber es ist eine gute Idee, ein paar Zeilen darüber zu schreiben, was Ihr Code tut. Ein paar Jahre ab jetzt können Sie vergessen, was ein Modul ist. Gute Dokumentation ist immer ein Muss, wenn du dich erinnern möchtest, was du in der Vergangenheit getan hast, decke ich die für Perl in Kapitel 8 verwendeten Dokumentationsstile ab. QuotDocumenting Perl Scripts. quot Für dieses Beispielmodul beginnt die head1-Anweisung die Dokumentation. Alles bis zum Cut-Statement wird vom Perl-Interpreter ignoriert. Als nächstes listet das Modul alle Funktionen auf, die von diesem Modul im EXPORT-Array exportiert werden. Das EXPORT-Array definiert alle Funktionsnamen, die von externem Code aufgerufen werden können. Wenn Sie keine Funktion in diesem EXPORT-Array auflisten, wird es nicht von externen Code-Modulen gesehen. Nach dem EXPORT-Array ist der Körper des Codes, eine Unterroutine zu einer Zeit. Nachdem alle Unterroutinen definiert sind, beendet die endgültige Anweisung 1 die Moduldatei. 1 muss die letzte ausführbare Zeile in der Datei sein. Schauen wir uns einige der in diesem Modul definierten Funktionen an. Die erste Funktion zu betrachten ist die einfache Datumsfunktion, Zeilen 43 bis 46, die das aktuelle UNIX Datum und Uhrzeit ausdruckt. Es gibt keine Parameter für diese Funktion, und es gibt nichts sinnvoll zurück an den Anrufer. Beachten Sie die Verwendung von meinem vor dem Datum variabel in Zeile 44. Das Schlüsselwort wird verwendet, um den Umfang der Variablen innerhalb der Datumsfunktionen curly Klammern zu begrenzen. Code zwischen geschweiften Klammern wird als Block bezeichnet. Variablen, die innerhalb eines Blocks deklariert sind, sind im Geltungsbereich innerhalb der geschweiften Klammern begrenzt. In 49 und 50 sind die lokalen Variablen Name und Thema für alle Funktionen sichtbar. Sie können auch Variablen mit dem lokalen Qualifikationsmerkmal deklarieren. Die Verwendung von local ermöglicht es, dass eine Variable in den Gültigkeitsbereich für den aktuellen Block sowie für andere Codeblöcke ist, die in diesem Block aufgerufen werden. Somit ist ein lokales x, das innerhalb eines Blocks deklariert ist, für alle nachfolgenden, in diesem Block aufgerufenen Blöcke sichtbar und kann referenziert werden. Im folgenden Beispielcode kann auf die Namensvariable ToTitled-Funktion zugegriffen werden, aber nicht die Daten im iPhone. 1 sub Letter :: ToTitled 2 lokal (name) shift 3 meine (telefon) shift Der Beispielcode für Letter. pm zeigte, wie man einen Parameter zu einem Zeitpunkt extrahiert. Die Unterroutine To () übernimmt zwei Parameter, um den Header für das Memo einzurichten. Die Verwendung von Funktionen innerhalb eines Moduls ist nicht anders als die Verwendung und Definition von Perl-Modulen innerhalb der gleichen Code-Datei. Parameter werden per Referenz übergeben, sofern nicht anders angegeben. Mehrere Arrays, die in eine Subroutine übergeben wurden, wenn nicht explizit mit dem Backslash dereferenziert, sind verkettet. Das Eingabefeld in einer Funktion ist immer ein Array von Skalarwerten. Übergeben von Werten durch Verweis ist der bevorzugte Weg in Perl, um eine große Menge von Daten in eine Unterroutine zu übergeben. (Siehe Kapitel 3. quotReferences. quot) Ein weiteres Beispielmodul: Finanzen Das Finanzierungsmodul, das in Listing 4.3 gezeigt wird, wird verwendet, um einfache Berechnungen für Kreditwerte zu liefern. Die Verwendung des Finanzmoduls ist einfach. Alle Funktionen werden mit den gleichen Parametern geschrieben, wie in der Formel für die Funktionen gezeigt. Schauen wir uns an, wie der zukünftige Wert einer Investition berechnet werden kann. Zum Beispiel, wenn Sie einige Dollar investieren, pv. In einer Anleihe, die einen festen Prozentsatz anbietet, r. Angewendet in bekannten Intervallen für n Zeiträume, was ist der Wert der Bindung zum Zeitpunkt des Ablaufs In diesem Fall verwenden Sie die folgende Formel: fv pv (1r) n Die Funktion, um den zukünftigen Wert zu erhalten, wird als FutureValue deklariert . Siehe Listing 4.3, um zu sehen, wie man es benutzt. Listing 4.3. Mit dem Finanzmodul. 1 usrbinperl - w 2 3 Push (Inc, pwd) 4 Verwendung Finanzen 5 6 Darlehen 5000.00 7 Apr 3.5 APR 8 Jahr 10 in Jahren. 9 10 ------------------------------------------------ ---------------- 11 Berechnen Sie den Wert am Ende des Darlehens, wenn Zinsen 12 jedes Jahr angewendet wird. 13 ------------------------------------------------- --------------- 14 Zeitjahr 15 fv1 Finanzen :: FutureValue (Darlehen, April, Zeit) 16 print quotn Wenn Zinsen am Ende des Geschäftsjahres angewendet werden 17 print quotn Der zukünftige Wert für a Darlehen von quot. Darlehen. Quotnquot 18 print quot bei einem APR von quot, apr. Für die Zeit, jdt. Jahrgang 19 printf quot ist 8.2f nquot. Fv1 20 21 ----------------------------------------------- ----------------- 22 Berechnen Sie den Wert am Ende des Darlehens, wenn Zinsen 23 jeden Monat angewendet wird. 24 ------------------------------------------------- --------------- 25 rate April 12 APR 26 Zeit Jahr 12 in Monaten 27 fv2 Finanzen :: FutureValue (Darlehen, Zinssatz, Zeit) 28 29 print quotn Wenn Zinsen am Ende des Geschäftsjahres angewendet werden Jeder Monat 30 print quotn Der zukünftige Wert für ein Darlehen von quot. Darlehen. Quotnquot 31 drucken bei einem APR von quot, apr. Für quot, time, quot monthquot 32 printf quot ist 8.2f nquot. Fv2 33 34 printf quotn Der Unterschied im Wert ist 8.2fquot, fv2 - fv1 35 printf quotn Deshalb durch Anwenden von Interesse an kürzeren Zeitspannen 36 printf quotn Wir sind eigentlich immer mehr Geld in interest. nquot Hier ist Stichprobeneingabe und Ausgabe von Listing 4.3. Testme Wenn Zinsen am Ende des Jahres angewendet werden Der zukünftige Wert für ein Darlehen von 5000 bei einem APR von 3,5 für 10 Jahre beträgt 7052,99 Wenn Zinsen am Ende eines jeden Monats angewendet wird Der zukünftige Wert für ein Darlehen von 5000 bei einem APR von 3,5 für 120 Monate ist 7091.72 Der Unterschied im Wert ist 38.73 Deshalb, indem wir Interesse an kürzeren Zeiträumen anwenden, sind wir eigentlich immer mehr Geld im Interesse. Die Offenbarung in der Ausgabe ist das Ergebnis des Vergleichs von Werten zwischen fv1 und fv2. Der fv1-Wert wird mit der Anwendung von Interesse einmal jährlich über die Lebensdauer der Anleihe berechnet. Fv2 ist der Wert, wenn die Zinsen jeden Monat auf den entsprechenden monatlichen Zinssatz angewendet werden. Das Paket Finance. pm wird in Listing 4.4 in seinen frühen Entwicklungsstadien gezeigt. Listing 4.4. Das Paket Finance. pm. 1 Paket Finanzen 2 3 erfordern Exporteur 4 ISA (Exporteur) 5 6 head1 Finance. pm 7 8 Finanzrechner - Finanzrechnungen leicht gemacht mit Perl 9 10 Kopf 2 11 Einsatz Finanzen 12 13 pv 10000.0 14 15 Rate 12,5 12 APR pro Monat. 16 17 Zeit 360 Monate für Ausleihen 18 19 fv FutureValue () 20 21 print fv 22 23 cut 24 25 EXPORT qw (FutureValue, 26 PresentValue, 27 FVofAnnuity, 28 AnnuityOfFV, 29 getLastAverage, 30 getMovingAverage, 31 SetInterest) 32 33 34 Globals, falls vorhanden 35 36 37 local defaultInterest 5.0 38 39 sub Finance :: SetInterest () 40 meine Rate Verschiebung () 41 defaultInterest Rate 42 printf quotn defaultInterest ratequot 43 44 45 -------------- -------------------------------------------------- ---- 46 Anmerkungen: 47 1. Der Zinssatz r wird im Wert von 0-100 angegeben. 48 2. Die in den Begriffen angegebene n ist der Satz, zu dem die Zinsen 49 angewandt werden. 50 51 ------------------------------------------------ -------------------- 52 53 ---------------------------- ---------------------------------------- 54 Gegenwärtiger Wert einer Investition in Höhe von 55 fv - Ein zukünftiger Wert 56 r - Rate pro Periode 57 n - Anzahl der Perioden 58 ---------------------------------- ---------------------------------- 59 sub Finance :: FutureValue () 60 mein (pv, r, n ) 61 mein fv pv ((1 (r100)) n) 62 return fv 63 64 65 ------------------------------ -------------------------------------- 66 Gegenwärtiger Wert einer Investition in Höhe von 67 fv - eine Zukunft Wert 68 r - Rate pro Periode 69 n - Anzahl der Periode 70 ------------------------------------ -------------------------------- 71 sub Finance :: PresentValue () 72 mein pv 73 mein (fv, r, N) 74 pv fv ((1 (r100)) n) 75 zurück pv 76 77 78 79 ----------------------------- --------------------------------------- 80 Erhalten Sie den zukünftigen Wert einer Annuität mit 81 mp - Monatliche Zahlung der Annuität 82 r - Rate pro Periode 83 n - Anzahl der Periode 84 -------------------------------- ------------------------------------ 85 86 sub FVofAnnuity () 87 meine fv 88 meine oneR 89 meine (Mp, r, n) 90 91 oneR (1 r) n 92 fv mp ((oneR - 1) r) 93 return fv 94 95 96 ------------------ -------------------------------------------------- 97 Holen Sie sich die Annuität aus den folgenden Bits von Informationen 98 r - Rate pro Periode 99 n - Anzahl der Periode 100 fv - Future Value 101 ---------------------- ---------------------------------------------- 102 103 sub AnnuityOfFV (Nr, r, n) 107 108 oneR (1 r) n 109 mp fv (r (oneR - 1)) 110 Rückkehr mp 111 112 113 - -------------------------------------------------- ---------------- 114 Holen Sie sich den Durchschnitt der letzten quotnquot Werte in einem Array. 115 ------------------------------------------------- ------------------- 116 Die letzte Zählzahl der Elemente aus dem Array in den Werten 117 Die Gesamtzahl der Elemente in den Werten ist in der Zahl 118 119 sub getLastAverage () 120 my (Count, number, values) 121 my i 122 123 my a 0 124 return 0 if (count 0) 125 für (i 0 ilt count i) 126 a Werte nummer - i - 1 127 128 einen Zählwert zurückgeben 129 130 131 --- -------------------------------------------------- --------------- 132 Holen Sie sich einen gleitenden Durchschnitt der Werte. 133 ------------------------------------------------- ------------------- 134 Die Fenstergröße ist der erste Parameter, die Anzahl der Elemente im 135 übergebenen Array ist als nächstes. (Dies kann leicht innerhalb der 136-Funktion mit der Skalar () - Funktion berechnet werden, aber die hier gezeigte Subroutine 137 wird auch verwendet, um zu veranschaulichen, wie man Zeiger übergibt.) Die Referenz auf das 138-Array von Werten wird als nächstes weitergeleitet, gefolgt von a Verweis auf den Ort 139 sind die Rückgabewerte zu speichern. 140 141 sub getMovingAve () 142 mein (count, number, values, movingAve) 143 my i 144 my a 0 145 my v 0 146 147 Rückgabe 0 if (count 0) 148 return -1 if (count gt number) 149 zurück - 2, wenn (count lt 2) 150 151 movingAve0 0 152 movingAvenumber - 1 0 153 für (i0 iltcounti) 154 v valuesi 155 av count 156 movingAvei 0 157 158 für (icount iltnumberi) 159 v valuesi 160 av count 161 v valuesi - count - 1 162 a - v count 163 movingAvei a 164 165 return 0 166 167 168 1 Schau auf die Deklaration der Funktion FutureValue mit (). Die drei Dollarzeichen zusammen bedeuten drei Skalarzahlen, die in die Funktion übergeben werden. Diese zusätzliche Scoping ist vorhanden für die Validierung der Art der Parameter in die Funktion übergeben. Wenn du einen String anstelle einer Zahl in die Funktion übergeben würdest, würdest du eine Nachricht sehr ähnlich zu diesem bekommen: Zu viele Argumente für Finanzen :: FutureValue bei. f4.pl Zeile 15, nahe Quottime) Ausführung von. f4.pl abgebrochen durch Kompilierungsfehler. Die Verwendung von Prototypen bei der Definition von Funktionen verhindert, dass Sie andere Werte als das, was die Funktion erwartet, senden. Verwenden Sie oder um ein Array von Werten zu übergeben. Wenn Sie durch Verweis übergeben, verwenden Sie oder um einen skalaren Verweis auf ein Array bzw. einen Hash zu zeigen. Wenn Sie den Backslash nicht verwenden, werden alle anderen Typen im Argumentliste Prototyp ignoriert. Andere Arten von Disqualifikatoren umfassen ein Und-Zeichen für einen Verweis auf eine Funktion, ein Sternchen für jeden Typ und ein Semikolon, um anzuzeigen, dass alle anderen Parameter optional sind. Nun schauen wir uns die lastMovingAverage-Funktionsdeklaration an, die zwei Integer in der Front angibt, gefolgt von einem Array. Die Art und Weise, wie die Argumente in der Funktion verwendet werden, besteht darin, jedem der beiden Skalare, Zählung und Nummer einen Wert zuzuordnen. Wohingegen alles andere an das Array geschickt wird. Schauen Sie sich die Funktion getMovingAverage () an, um zu sehen, wie zwei Arrays übergeben werden, um den gleitenden Durchschnitt auf einer Liste von Werten zu erhalten. Der Weg, um die Funktion getMovingAverage aufzurufen, wird in Listing 4.5 angezeigt. Listing 4.5. Mit der gleitenden Mittelfunktion. 1 usrbinperl - w 2 3 push (Inc, pwd) 4 Verwendung Finanzen 5 6 Werte (12,22,23,24,21,23,24,23,23,21,29,27,26,28) 7 mv ( 0) 8 Größe Skalar (Werte) 9 print quotn Werte zur Arbeit mit nquot 10 print quot Anzahl Werte Größe nquot 11 12 ------------------------ ---------------------------------------- 13 Berechnen Sie den Durchschnitt der obigen Funktion 14 - -------------------------------------------------- ------------- 15 ave Finanzen :: getLastAverage (5, Größe, Werte) 16 print quotn Durchschnitt der letzten 5 Tage ave nquot 17 18 Finanzen :: getMovingAve (5, Größe, Werte, mv ) 19 print quotn Moving Average mit 5 Tage Fenster n nquot Heres die Ausgabe von Listing 4.5: Werte zur Arbeit mit Anzahl der Werte 14 Durchschnitt der letzten 5 Tage 26.2 Die Funktion getMovingAverage () nimmt zwei Skalare und dann zwei Verweise auf Arrays als Skalare. Innerhalb der Funktion werden die beiden Skalare zu den Arrays zur Verwendung als numerische Arrays dereferenziert. Der zurückgegebene Satz von Werten wird in den als zweiten Referenz übergebenen Bereich eingefügt. Wurden die Eingabeparameter nicht für jedes referenzierte Array angegeben, wäre die moveAve-Array-Referenz leer und hätte Fehler zur Laufzeit verursacht. Mit anderen Worten, die folgende Deklaration ist nicht korrekt: sub getMovingAve () Die daraus resultierende Fehlermeldung von Fehlermeldungen aus einem schlechten Funktionsprototyp ist wie folgt: Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 128. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 128. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 128. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 128. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 128. Verwendung von uninitialisiertem Wert bei Finance. pm Zeile 133. Verwendung von nicht initialisiertem Wert Bei Finance. pm Zeile 135. Verwendung von uninitialisiertem Wert bei Finance. pm Zeile 133. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 135. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 133. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 135 Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 133. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 135. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 133. Verwendung von nicht initialisiertem Wert bei Finance. pm Zeile 135. Verwendung von nicht initialisiertem Wert bei Finance. pm line 133. Use of uninitialized value at Finance. pm line 135. Use of uninitialized value at Finance. pm line 133. Use of uninitialized value at Finance. pm line 135. Use of uninitialized value at Finance. pm line 133. Use of uninitialized value at Finance. pm line 135. Use of uninitialized value at Finance. pm line 133. Use of uninitialized value at Finance. pm line 135. Average of last 5 days 26.2 Moving Average with 5 days window This is obviously not the correct output. Therefore, its critical that you pass by reference when sending more than one array. Global variables for use within the package can also be declared. Look at the following segment of code from the Finance. pm module to see what the default value of the Interest variable would be if nothing was specified in the input. (The current module requires the interest to be passed in, but you can change this.) Heres a little snippet of code that can be added to the end of the program shown in Listing 4.5 to add the ability to set interest rates. 20 local defaultInterest 5.0 21 sub Finance::SetInterest() 22 my rate shift() 23 rate -1 if (rate lt 0) 24 defaultInterest rate 25 printf quotn defaultInterest ratequot 26 The local variable defaultInterest is declared in line 20. The subroutine SetInterest to modify the rate is declared in lines 21 through 26. The rate variable uses the values passed into the subroutine and simply assigns a positive value for it. You can always add more error checking if necessary. To access the defaultInterest variables value, you could define either a subroutine that returns the value or refer to the value directly with a call to the following in your application program: Finance::defaultInterest The variable holding the return value from the module function is declared as my variable . The scope of this variable is within the curly braces of the function only. When the called subroutine returns, the reference to my variable is returned. If the calling program uses this returned reference somewhere, the link counter on the variable is not zero therefore, the storage area containing the returned values is not freed to the memory pool. Thus, the function that declares my pv and then later returns the value of pv returns a reference to the value stored at that location. If the calling routine performs a call like this one: Finance::FVofAnnuity(monthly, rate, time) there is no variable specified here into which Perl stores the returned reference therefore, any returned value (or a list of values) is destroyed. Instead, the call with the returned value assigned to a local variable, such as this one: fv Finance::FVofAnnuity(monthly, rate, time) maintains the variable with the value. Consider the example shown in Listing 4.6, which manipulates values returned by functions. Listing 4.6. Sample usage of the my function. 1 usrbinperl - w 2 3 push(Inc, pwd) 4 use Finance 5 6 monthly 400 7 rate 0.2 i. e. 6 APR 8 time 36 in months 9 10 print quotn ------------------------------------------------quot 11 fv Finance::FVofAnnuity(monthly, rate, time) 12 printf quotn For a monthly 8.2f at a rate of 6.2f for d periodsquot, 13 monthly, rate, time 14 printf quotn you get a future value of 8.2f quot, fv 15 16 fv 1.1 allow 10 gain in the house value. 17 18 mo Finance::AnnuityOfFV(fv, rate, time) 19 20 printf quotn To get 10 percent more at the end, i. e. 8.2fquot, fv 21 printf quotn you need a monthly payment value of 8.2fquot, mo, fv 22 23 print quotn ------------------------------------------------ nquot Here is sample input and output for this function: testme ------------------------------------------------ For a monthly 400.00 at a rate of 0.20 for 36 periods you get a future value of 1415603.75 To get 10 percent more at the end, i. e. 1557164.12 you need a monthly payment value of 440.00 ------------------------------------------------ Modules implement classes in a Perl program that uses the object-oriented features of Perl. Included in object-oriented features is the concept of inheritance . (Youll learn more on the object-oriented features of Perl in Chapter 5. quotObject-Oriented Programming in Perl. quot) Inheritance means the process with which a module inherits the functions from its base classes. A module that is nested within another module inherits its parent modules functions. So inheritance in Perl is accomplished with the :: construct. Heres the basic syntax: SuperClass::NextSubClass. ThisClass. The file for these is stored in. SuperClassNextSubClass133 . Each double colon indicates a lower-level directory in which to look for the module. Each module, in turn, declares itself as a package with statements like the following: package SuperClass::NextSubClass package SuperClass::NextSubClass::EvenLower For example, say that you really want to create a Money class with two subclasses, Stocks and Finance . Heres how to structure the hierarchy, assuming you are in the usrlibperl5 directory: Create a Money directory under the usrlibperl5 directory. Copy the existing Finance. pm file into the Money subdirectory. Create the new Stocks. pm file in the Money subdirectory. Edit the Finance. pm file to use the line package Money::Finance instead of package Finance . Edit scripts to use Money::Finance as the subroutine prefix instead of Finance:: . Create a Money. pm file in the usrlibperl5 directory. The Perl script that gets the moving average for a series of numbers is presented in Listing 4.7. Listing 4.7. Using inheriting modules. 1 usrbinperl - w 2 aa pwd 3 aa . quotMoneyquot 4 push(Inc, aa) 5 use Money::Finance 6 values ( 12,22,23,24,21,23,24,23,23,21,29,27,26,28 ) 7 mv (0) 8 size scalar(values) 9 print quotn Values to work with nquot 10 print quot Number of values size nquot 11 ---------------------------------------------------------------- 12 Calculate the average of the above function 13 ---------------------------------------------------------------- 14 ave Money::Finance::getLastAverage(5,size, values) 15 print quotn Average of last 5 days ave nquot 16 Money::Finance::getMovingAve(5,size, values, mv) 17 foreach i (values) 18 print quotn Moving with 5 days window mvi nquot 19 20 print quotn Moving Average with 5 days window n nquot Lines 2 through 4 add the path to the Money subdirectory. The use statement in line 5 now addresses the Finance. pm file in the. Money subdirectory. The calls to the functions within Finance. pm are now called with the prefix Money::Finance:: instead of Finance:: . Therefore, a new subdirectory is shown via the :: symbol when Perl is searching for modules to load. The Money. pm file is not required. Even so, you should create a template for future use. Actually, the file would be required to put any special requirements for initialization that the entire hierarchy of modules uses. The code for initialization is placed in the BEGIN() function. The sample Money. pm file is shown in Listing 4.8. Listing 4.8. The superclass module for Finance. pm . 1 package Money 2 require Exporter 3 4 BEGIN 5 printf quotn Hello Zipping into existence for younquot 6 7 1 To see the line of output from the printf statement in line 5, you have to insert the following commands at the beginning of your Perl script: use Money use Money::Finance To use the functions in the Stocks. pm module, you use this line: use Money::Stocks The Stocks. pm file appears in the Money subdirectory and is defined in the same format as the Finance. pm file, with the exceptions that use Stocks is used instead of use Finance and the set of functions to export is different. A number of modules are included in the Perl distribution. Check the usrlibperl5lib directory for a complete listing after you install Perl. There are two kinds of modules you should know about and look for in your Perl 5 release, Pragmatic and Standard modules. Pragmatic modules, which are also like pragmas in C compiler directives, tend to affect the compilation of your program. They are similar in operation to the preprocessor elements of a C program. Pragmas are locally scoped so that they can be turned off with the no command. Thus, the command no POSIX turns off the POSIX features in the script. These features can be turned back on with the use statement. Standard modules bundled with the Perl package include several functioning packages of code for you to use. Refer to appendix B, quotPerl Module Archives, quot for a complete list of these standard modules. To find out all the. pm modules installed on your system, issue the following command. (If you get an error, add the usrlibperl5 directory to your path.) find usrlibperl5 - name perl quot. pmquot - print Extension modules are written in C (or a mixture of Perl and C) and are dynamically loaded into Perl if and when you need them. These types of modules for dynamic loading require support in the kernel. Solaris lets you use these modules. For a Linux machine, check the installation pages on how to upgrade to the ELF format binaries for your Linux kernel. The term CPAN (Comprehensive Perl Archive Network) refers to all the hosts containing copies of sets of data, documents, and Perl modules on the Net. To find out about the CPAN site nearest you, search on the keyword CPAN in search engines such as Yahoo. AltaVista, or Magellan. A good place to start is the metronet site . This chapter introduced you to Perl 5 modules and described what they have to offer. A more comprehensive list is found on the Internet via the addresses shown in the Web sites metronet and perl . A Perl package is a set of Perl code that looks like a library file. A Perl module is a package that is defined in a library file of the same name. A module is designed to be reusable. You can do some type checking with Perl function prototypes to see whether parameters are being passed correctly. A module has to export its functions with the EXPORT array and therefore requires the Exporter module. Modules are searched for in the directories listed in the Inc array. Obviously, there is a lot more to writing modules for Perl than what is shown in this chapter. The simple examples in this chapter show you how to get started with Perl modules. In the rest of the book I cover the modules and their features, so hang in there. I cover Perl objects, classes, and related concepts in Chapter 5.With weight vector I mean the vector with weights that you have to multiply the observations in the window that slides over your data with so if you add those products together it returns the value of the EMA on the right side of the window. For a linear weighted moving average the formula for finding the weight vector is: (1:n)sum(1:n) (in R code). This series of length n adds up to 1. For n10 it will be 0.01818182 0.03636364 0.05454545 0.07272727 0.09090909 0.10909091 0.12727273 0.14545455 0.16363636 0.18181818 the numbers 1 to 10 55, with 55 the sum of the numbers 1 to 10. How do you calculate the weight vector for an exponential moving average (EMA) of length n if n is the length of the window, then alphalt-2(n1) and ilt-1:n so EmaWeightVectorlt-((alpha(1-alpha)(1-i))) Is this correct Even though the EMA is not really confined to a window with a start and an end, shouldnt the weights add up to 1 just like with the LWMA Thanks Jason, any pointers of how to approximate the EMA filter to any desired precision by approximating it with a long-enough FIR filter There39s a perl script on en. wikipedia. orgwikihellip that made the image of the EMA weight vector, but I don39t understand it: if they set the number of weights to 15 why are there 20 red bars instead of 15 ndash MisterH Dec 19 12 at 22:40When working on the stock market, calculated indicators that include 28-day averages, 14-day averages, etc. need to be calculated. Furthermore every day the average needs to update to include the latest days closehighlowvolume. Now often the array needs to be looped through to find the sum, average, max, and min values. I though that a queue (in the form of a dynamic array or linked list or anything else you can think of) seems like the perfect data structure for this based on the FIFO method of entryexit. How does the efficiency and scalability of queues compare to hashes When running a Perl script the queue will not be in memory and will therefore have to be initialized and worked on (values initialized from a CSV file), I know this is pretty unrelated, but which data structure would be the best to use with a Perl script that executes on a daily schedule asked Feb 5 13 at 19:43 Not enough information here. Are you processing an entire days worth of quotes to get your daily highlowlast Are you doing the averages on a per instrument basis With any moving average, you can just use a list of values that make up the sum of the average. As a new value gets added, one drops off, and recalculate. So a hash of lists if your doing by instrument and calculate on the fly. I add a line to the CSV with closehighlow at the close of the day. the data is scraped from a feed. The averages are calculated per share, at the end of the day and inputted into a db. after which indicators are calculated using the values. Possibly an even better way to do it is to just save the 28th and 14th days close. then when updating (add new close to the old moving average and subtract the 28th 14th stored value. Wait I dunno ndash surfer190 Feb 5 13 at 20:55 user1439659 That works, and is more or less how you do it. Keep the sum, then do the addsubtractdivide. Just didn39t know how you were deriving the data. Things change when you have to rip through 1.5 billion records vs. having the closing values. ndash Mike Feb 5 13 at 21:10 What is most efficient really depends. Hashes are unordered. They can look up values in nearly-constant time by a string key. A lookup is computationally expensive, and at least an order of magnitude slower than an array lookup. How well a hash performs depends on the number of buckets and the number of keys. However, a hash lookup will be faster than looping through an array to find an element for all non-trivial cases. Hashes require more space than an array. Arrays in Perl have both the characteristics of an array (random access) and a doubly linked list (via push, pop, shift, unshift). They are easy to use, and fast enough. If more than one element is to be addedremoved, either use a slice, or the splice function. splice is a generalisation of push. unshift. and is faster than looping. Strings can be used to store an array of integers. This is extremely efficient, but also quite limited (only ints). Using Strings has the characteristics of an array (random access) and of a single linked list (appending is simple with . ). Other operations are reasonably fast as well ( substr has many uses). The pragmatic programmer will use arrays for most sequential data. He can also leverage the efficient functions from List::Util and List::MoreUtils that provide functions like sum. average. max and min (written in C for speed). When you are building a list of values, and only need a fixed amount, either do this when you add a new element: This is space-efficient but may be slower than simply building the list, and doing To access only a certain part of the array (without allocating a new variable), use slices: If you want to use hashes, but know all possible fields at compile time, you can define constant names for the fields, and use an array instead. So dont do When working with deeply nested data, it can sometimes pay off to cache nested references instead of recalculating them at every access: Hi thanks for your input. I think a singly linked list would be most efficient with FILO (first in, last out). EG. I get the close for a particular day, that becomes head node of list, then the previous 28th falls off end of list and the moving average can be calculated again. Instead of inserting into a db, and calculating the 28 day moving average from there. Hang on that is the same thing. ndash surfer190 Feb 17 13 at 19:49 user1439659 That would be a FIFO, not a FILO. Don39t model FIFOs yourself (this is very inefficient), but use the builtin arrays. Those implement the characteristics of a double linked list. You will have to assert the fixed length yourself. See my first code example after quotuse arraysquot. Any way: premature optimization is the root of all evil. ndash amon Feb 17 13 at 20:06 If you are calculating these things once a day. use the easiest data structure to code Does it really take so much time to compute If yes, go on reading. The sum and average might be easier. If what you add are integers, you can use a FIFO and keep the sum in a variable. Whenever you insert or remove an element, update the sum accordingly (add or subtract). If you add floating point values, then the method described above might lead to cumulative errors. This might happen if the values are of very different magnitudes andor the series is very long. In this case, you would need something more complicated (see below). For the max and min, the most efficient data structures are maxmin-heaps. Note that you can embed them in arrays. You would need to have them cross-referenced with the elements of the FIFO queue in order to find immediately the element that has to be removed every time. The most general solution would be an augmented self-balanced tree. Augmented data structures are explained in chapter 14 of Introduction to Algorithms by Cormen, Leiserson, Rivest and Stein. Basically, the tree would contain one element of your data sequence in every node. Every node would contain also the sum, min and max of its subtree. Every time you update a node, you have to update the sum, max and min in all the path from that node to the root. in the root you have the global sum, max and min. You can find a C implementation of augmented self-balanced trees here . Though, since you only want the sum, min and max of a fixed number of elements, and you always insert at one end and remove at the other, you can make it much simpler. You only need a circular buffer and an array-embedded tree (see how to embed such tree in an array ). The tree would contain partial sum, min and max values, as in the augmented trees described before. The advantage is that you dont need to rebalance the tree because you never insertremove in the middle of the sequence, and the tree always has the same size. In order to have the statistics for the last 28 days, the last 14 days, the last week, and the last 3 days (for example), you would use a circular buffer and an array-embedded tree for every period: one for the last 3 days, another for the previous 4 (7 minus 3) days, another for the previous 7 days, and so on. Every day, you would take the last datum of every buffer and insert it in the next one. answered Feb 6 13 at 6:54 Thanks for your input. There are - 470 shares, about 10 calculations each. I haven39t tested but I think it may take significant time to compute. The easiest to code would be inserting records into db daily and computing from there. If I were to use some of the data structures you suggest, would it be feasible to store 470 of these data structures in memory for the whole day only to be updated once a day ndash surfer190 Feb 17 13 at 19:55 user1439659 There is only one way to find out (I don39t know the exact amount of data, the data structure, your OS, hardware, Perl compilation flags). The numbers you provide look reasonable even for low-powered machines, but I wouldn39t keep the data in memory all the time. It might be best to write working code, and then optimize for speed andor memory once you can test and profile working code. But no earlier. Premature optimization ndash amon Feb 17 13 at 20:26 I would just use a simple hash with keys being some stringified or numericized representation of the timestamp and the value being what your data is associated with that time series item. You can sort the keys of the hash, e. g. and loop through the last 28 or 14 etc. then retrieve the values from the hash.

No comments:

Post a Comment