Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - Elementares in Pascal
Torsten - Di 01.10.02 19:48
Titel: Elementares in Pascal
Moinsen Leute!
Mal eine elementare Frage zu Pascal.
Ich habe den ganzen Sommer über keinen Rechner gesehen, also viel vergessen. Besonders, was reines Pascal angeht.
Also, ich will in einem kleinen Programm das Skalar-Produkt im n-dimensionalen Raum berechnen.
Die eigentliche Berechnung ist mir eigentlich klar, nur die Arrays gefallen mir nicht so recht.
Ich kann euch ja mal meinen Entwurf zeigen.
Zu beachten ist noch, dass das Skalarprodukt später mittels "s:=Skal_Prod(n, V, W)" aufgerufen werden soll.
n ist also die Dimension (2,3,4,...) und V bzw. W die Vektoren.
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| program skalar;
function Skal_Prod(n:Integer; x:array of Real; y:array of Real):Real; var i: Integer;
begin i:=1; Skal_Prod:=0.0;
repeat Skal_Prod:=Skal_Prod + (x[i]*y[i]); i:=i+1; until i > n; end;
begin // ab hier nun das Hauptprogramm end. |
Nun noch eine Fragen.
In Zeile "Skal_Prod:=Skal_Prod + (x[i]*y[i]);" bekomme ich einen Compiler-Fehler!
Wieso? Geht das so nicht?
Ach ja, hat jemand rein zufällig ein gutes Forum für reines Pascal in Verbindung mit Mathe?
Fragende Grüße
Torsten
Christian S. - Di 01.10.02 19:54
Hi!
Pascal ist bei mir jetzt schon 3 Jahre her, aber mit einer Function darfst Du in Pascal glaube ich keine solche Zuweisung machen. Definiere Dir doch eine lokale Variable vom Typ Real, mit der Du die gleichen Berechnungen machst, die Du aber erst ganz am Ende Skal_Prod zuweist.
Bei Delphi fangen Arrays, wie Du sie verwendest, mit dem Index 0 an, ist das bei Pascal anders?
MfG,
Peter
Torsten - Di 01.10.02 19:59
Hallo!
OK, das mit der Variablen habe ich mir auch überlegt. Ich war jedoch der Meinung, dass es auch so geht. aber man lernt ja immer dazu.
Tja, Arrays in Pascal. Ich denke mal auch, dass sie bei 0 beginnen. Also ähnlich C oder Delphi. Sicher bin ich mir jedoch auch nicht, daher die Frage.
Kann man den ganzen Kram nicht ohnehin irgendwie besser machen?
Grüße
Torsten
Christian S. - Di 01.10.02 20:07
Hi!
Ich glaube nicht, dass man das ganze noch verbessern kann. Die Laufzeit ist glaube ich mit einer linearen Abhängigkeit von n ganz in Ordnung. Man kann natürlich jetzt versuchen, herauszufinden, ob Inc(i) schneller ausgeführt wird als i:=i+1; aber ganz ehrlich halte ich das für maßlos übertrieben.
MfG,
Peter
P.S.: Definiere doch alle Winkel als 90°, dann ist das Skalarprodukt ganz einfach Null!
Klabautermann - Di 01.10.02 20:33
Titel: Re: Elementares in Pascal
Hallo,
Torsten hat folgendes geschrieben: |
Quelltext 1:
| Skal_Prod:=Skal_Prod + (x[i]*y[i]); |
|
Skal_Prod ist deine funktion, also ist der erste Teil der Zeile (Skal_Prod:=) Ok. Danch rufst du aber wieder Skal_Prod auf. Das währe generell auch kein Problem, nur müsstest du dann:
1. auch die benötigten Parameter übergeben.
2. Eine abbruchbedingung für die benötigte Rekursion schreiben.
Ich glaube aber nicht, das du überhaupt eine Rekursion machen willst.
Wenn du das ganze in Delphi Implementierst, kannst du Result verwenden (ich weis nicht mit welcher Verion das eingeführt wurde, vieleicht gab es das schon in neueren Turbo Pascal Versionen).
Dann sähe deine Funktion so aus:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| function Skal_Prod(n:Integer; x:array of Real; y:array of Real):Real; var i: Integer; begin i:=1; Result:=0.0; repeat Result:=Result + (x[i]*y[i]); i:=i+1; until i > n; end; |
Ansonsten musst du tatsächlich zu einer Hilfsvariable greifen.
Mit freundlichen Grüßen
Klabautermann
Torsten - Di 01.10.02 21:09
Moinsen!
Besten Dank für die Antworten.
Ja, result kenne ich von Delphi auch. Aber eben nicht unter Pascal. Und da bin ich schon seit bestimmt 10 Jahren raus (habe auch nicht viel mit gearbeitet).
Habe es aber eben getestet.
Ich arbeite mit GnuPascal unter Linux.
result scheint auch hier zu funktionieren.
Um es aber auch für andere Compiler zu schreiben, werde ich eine globale Variable verwenden.
Grüße
Torsten
Christian S. - Di 01.10.02 21:35
Eine globale Variable?
Torsten - Di 01.10.02 21:43
Sorry, falsch ausgedrückt.
Gilt natürlich nur für die Funktion.
Ich habe aber wieder ein anderes Problem.
Und zwar mit einem dynamischen Array.
So, mal eben das Programm:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29:
| program skalar; var i: Integer; n: Integer; v,w: array of Real;
{die eigentliche Funktion} function Skal_Prod(n:Integer; x:array of Real; y:array of Real):Real; var i: Integer; result: Real;
begin i:=1; result:=0.0;
repeat result:=result + (x[i]*y[i]); i:=i+1; until i > n; return result; end;
{ eigentliches Hauptprogramm } begin writeln('Das Skalarprodukt:'); // s:=Skal_Prod(......) end. |
Der Compiler meldet in der 5. Zeile bei
"v,w: array of Real;"
einen Fehler (parse error befor 'of')
Hö?
Wieso?
Dynamische Arrays gibt es doch bei Pascal.
Grüße
Torsten
Christian S. - Di 01.10.02 22:14
Hi!
Ich habe jetzt nochmal mein altes TP7 herausgekramt und bei dem Code, den Du verwendest, meckert er. Anscheinend kannst Du Arrays ohne Größenangabe nur als Parameter übergeben. Aber als ich TP programmiert habe, war ich noch nicht so weit, dass ich überhaupt auf die Idee von dynamischen Arrasy gekommen wäre; also kann es sein, dass es da irgendeinen Code gibt, wie man sie doch verwenden kann.
MfG,
Peter
P.S.: Die Fehlermeldung bei mir: "[" oder "(." erwartet
Torsten - Di 01.10.02 22:20
Moinsen!
Verdammte Axt.
Anscheinend gibt es doch keine dynamischen Arrays.
Eben doch nur als Parametrübergabe.
Naja, dann muss ich mir was einfallen lassen.
Dumm ist nur, dass ich die dort gebrauchen könnte.
Denn man weiss ja vorher nicht, in welcher Dimension das das Skalarprodukt gebildet werden soll.
Grüße
Torsten
Christian S. - Di 01.10.02 22:34
Hi!
Könntest Du das ganze nicht als Records in temporären Dateien speichern? Die kannst Du beliebig groß machen. Ist zwar ein Algorithmus mit der Brechstange aber es könnte funktionieren!
MfG,
Peter
CenBells - Di 01.10.02 22:39
Zitat: |
Ich glaube nicht, dass man das ganze noch verbessern kann. Die Laufzeit ist glaube ich mit einer linearen Abhängigkeit von n ganz in Ordnung. Man kann natürlich jetzt versuchen, herauszufinden, ob Inc(i) schneller ausgeführt wird als i:=i+1; aber ganz ehrlich halte ich das für maßlos übertrieben. |
Inc(i) wird schneller ausgeführt, als i := i+1;
Gruß
Ken
Torsten - Di 01.10.02 22:40
Hui, das wäre mir dann doch zu viel.
Es war eigentlich nur ein Test.
Ich habe nämlich gerade in einem alten Pascal-Buch gestöbert.
Dort stand die Aufgabe, dass man eine Funktion entwickeln soll, die das Skalarprodukt errechnet.
Diese Funktion sollte dann mit Wertübergabe aufgerufen werden. Aber das drumherum war weniger interessant.
Ich wollte es dennoch gerne probieren (ohne Erfolg).
Grüße
Torsten
Christian S. - Di 01.10.02 22:52
Ireniceus hat folgendes geschrieben: |
Inc(i) wird schneller ausgeführt, als i := i+1;
|
Hatte ich schon vermutet, ansonsten würde es kaum Sinn machen, eine solche Funktion zu implementieren.
MfG,
Peter
Torsten - Di 01.10.02 23:00
Moinsen!
Nochmal zum dynamischen Array.
In C wüsste ich, wie zu implementieren (malloc).
Auch in Delphi.
Nur eben nicht in Pascal.
Aber: Man kann das auch als verkette Liste ausführen.
Doch ich will mal nicht übertreiben.
Außer jemand hat einen einfachen, genialen Vorschlag. ;)
Grüße
Torsten
Klabautermann - Di 01.10.02 23:11
Hallo!
Was ist an der Verketteten liste so schlim?
Torsten - Di 01.10.02 23:46
Moinsen!
Och naja, irgendwie sträube ich mich immer etwas dagegen.
Hast Du etwa eine Lösung für meine Aufgabe?
Grüße
Torsten
Klabautermann - Mi 02.10.02 01:00
Hallo,
da verlangst du was zu dieser späten Stunde. Aber gut, dann werde ich mal schnell was hintippen.
Aber eins vorweg: Aufgrund der vortgeschrittenden Zeit habe ich das nicht getestet oder nochmal genauer überprüft. Wenn es ein Problem gibt können wir Morgen nochmal drüber reden:
Also hier die Datentypen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| TYPE pRealList = ^tRealList; tRealList = PACKED RECORD Value : Real; Next : pRealList; END; |
Die Variablendeklaration:
Delphi-Quelltext
1: 2:
| VAR v, w : pRealList; |
Vergiss die Initialisierung nicht:
Und das Werkzeug:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
| procedure Appent2RealList(Value : Real; aList : pRealList); VAR Runner, NewEle : pRealList; BEGIN NEW(NewEle); NewEle^.Value := Value; NewEle.Next := NIL; Runner := aList; IF (Runner = NIL) THEN aList := NewEle ELSE BEGIN WHILE (Runner^.Next <> NIL) DO Runner := Runner^.Next; Runner^.Next := NewEle; END; END; function RealListLength(aList : pRealList) : LongInt; VAR Runner : pRealList; BEGIN Result := 0; Runner := aList; WHILE (Runner <> NIL) DO BEGIN INC(Result); Runner := Runner^.Next; END; END; function GetRealValue(aIndex : LongInt; aList : pRealList) : Real; VAR Runner : pRealList; i : LongInt; BEGIN Result := 0; IF (aIndex < RealListLength(aList)) THEN BEGIN Runner := aList; FOR i := 1 TO aIndex DO Runner := Runner^.Next; Result := Runner^.Value; END; END; procedure RemoveRealValue(aIndex : LongInt; aList : pRealList); VAR Runner, tmp : pRealList; i : LongInt; BEGIN IF (aIndex < RealListLength(aList)) THEN BEGIN Runner := aList; IF (aIndex = 1) THEN BEGIN tmp := Runner; aList := aList^.Next; END ELSE BEGIN FOR i := 1 TO aIndex - 1 DO Runner := Runner^.Next; tmp := Runner^.Next; Runner^.Next := Runner^.Next^.Next; END; Dispose(tmp); END; END; procedure ClearRealList(aList : pRealList); VAR tmp : pRealList; BEGIN WHILE (aList <> NIL) DO BEGIN tmp := aList; aList := aList.Next; Dispose(tmp); END; END; |
Und jetzt mach' was draus ;).
Gruß
Klabautermann
Torsten - Mi 02.10.02 09:12
Moinsen!
Na hossa, das schaut ja wirklich gut aus.
Dennoch mag ich keine Listen, geschweige denn verkette Listen.
Aber bei Deinem Code sehe ich gut durch. Ist auch alles wunderbar enthalten (insert, remove, Länge,..)
Eigentlich wollte ich ja nicht so weit mit meinem Problem gehen, doch eventuell findet sich etwas Zeit.
Besten Dank dafür.
Grüße
Torsten
Klabautermann - Mi 02.10.02 16:00
Hallo,
Torsten hat folgendes geschrieben: |
Dennoch mag ich keine Listen, geschweige denn verkette Listen. |
das ist schade, sie sind sehr Praktisch und im Klassischen Pascal der Standard-Weg für Dynamische Speicherverwaltung. Mann muss sich nur einmal richtig damit auseinander setzen, dann verlieren sie ihren Schrecken. :mahn:
Torsten hat folgendes geschrieben: |
Aber bei Deinem Code sehe ich gut durch. Ist auch alles wunderbar enthalten (insert, remove, Länge,..) |
Ja, wenn man sich am Anfang ein wenig Arbeit macht, kann man später sehr konfortabel Arbeiten und hat auch keine sorgen mehr mit den Verketteten listen ;).
Torsten hat folgendes geschrieben: |
Eigentlich wollte ich ja nicht so weit mit meinem Problem gehen, doch eventuell findet sich etwas Zeit. |
Ich zwinge dich ja nicht. Wie gesagt, wenn es dir hilft, dann viel Spass damit. Wenn nicht, vieleicht lernt ein mitleser was draus :think:.
Torsten hat folgendes geschrieben: |
Besten Dank dafür. |
Bitteschön, ich hatte Spaß dabei, denn heutzutage kommt man ja nicht mehr so oft dazu (denn Dynamische Arrays oder tList finde ich auch schnuckelig und verwende sie daher).
Gruß
Klabautermann
Torsten - Mi 02.10.02 17:16
Moinsen!
OK, die Geschichte mit dem Spass kann ich wohl nachvollziehen.
Ich finde Zeiger und doppelt referenzierte Zeiger in C auch unheimlich interessant. Ist zwar etwas pervers, macht aber irgendwie Laune.
Nun muss ich den Spass nur noch auf Pascal übertragen.
Sehe ich übrigens ebenso. Am Anfang etwas Arbeit, danach komfortabel Klotzen.
Für die kleine Aufgabe war es aber nicht wirklich angebracht. Wollte eben nur mal ein wenig testen (was nicht heissen soll, dass Deine Lösung mich nicht freut).
Grüße
Torsten
Indeterminatus - Fr 04.10.02 12:39
Zitat: |
Inc(i) wird schneller ausgeführt, als i := i+1;
|
Obwohl es bei einer TP-Compilerversion ab 6.0 auch schon egal ist, weil eine Erhöhung einer Variable um einen konstanten ganzzahligen Wert mittels Wertzuweisung (i := i+x, wobei x Element aus N) durch die Funktion Inc ersetzt wird, vorausgesetzt, die Optimierung für den Compilerdurchlauf wurde eingeschaltet...
Torsten - Fr 11.10.02 00:37
Moinsen!
Noch mal eine Frage zu mehrdimensionalen Arrays.
Also, ein gutes Beispiel sind mal wieder Vektoren. Jene können ja nun im n-dimensionalen Raum bestehen.
Nehmen wir mal, wir arbeiten im 3-dimensionalen Raum und haben zwei Vektoren.
Dann dürfte doch folgendes laufen:
Quelltext
1:
| type TMyArray = array [0..2] of array [0..2] of Integer; |
Oder sehe ich das irgendwie falsch?
Aber:
Wie kann man nun realisieren, dass man beispielsweise eine beliebige Anzahl von Vektoren nutzen kann?
Fragende Grüße
Torsten
Udontknow - Fr 11.10.02 08:00
Hi!
Nun, beliebig viele kannst du in einem dynamischen Array unterbringen. Noch schöner ist aber natürlich die Benutzung eines TList-Objekts, und bei Vektoren ist sowieso angebrachter, eine Klasse TVektor zu entwerfen, um in dieser dann auch benötigte Methoden unterzubringen (Anwendung einer Matrix auf einen Vektor z.B.).
Cu, :D
Udontknow
Torsten - Fr 11.10.02 08:37
@UdontKnow
Eigentlich war ich der Meinung, dass ich über Pascal sprach.
Grüße
Torsten
Udontknow - Fr 11.10.02 08:43
Naja gut, dann belassen wir es bei dynamischen Arrays.
Torsten - Fr 11.10.02 08:53
Moinsen!
Danke für die Antwort.
So wie es Klabautermann mir schilderte, will ich die Arrays aber nicht machen. Es gibt definitiv noch einen anderen Weg.
Mein Prof will aber einfach nicht damit rausrücken.
Er meinte, man könne das auch über type realisieren.
Grüße
Torsten
Udontknow - Fr 11.10.02 10:25
Hallo, ich nochmal! :)
Brutal gehts natürlich auch:
Reservierung von Speicher per Getmem für folgenden Record:
Quelltext
1: 2: 3: 4: 5: 6: 7:
| type PVektor=^TVektor;
TVektor=record Data:Array[0..2] of integer; NextVektor:PVektor; end; |
Du erzeugst dann weitere Elemente, indem du
Quelltext
1:
| GetMem(NextVektor,SizeOf(TVektor)); |
aufrufst.
Du verkettest sozusagen die einzelnen Elemente in eine Richtung. Um auf einzelne Elemente zuzugreifen, solltest du dann am besten dir eine rekursive Routine basteln, die dir dann z.B. einen Pointer auf das Nte Element liefert.
Cu,
Udontknow
PS: So im nachhinein überlegt, braucht man für die Ermittlung des nten Elements keine Rekursion... :roll:
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!