Dynamische Arrays - ins negative Erweiterbar?
-
- Lazarusforum e. V.
- Beiträge: 2808
- Registriert: Fr 22. Sep 2006, 10:38
- OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
- Wohnort: Hessen
- Kontaktdaten:
Dynamische Arrays - ins negative Erweiterbar?
Hallo Leute!
Habe wiedermal eine Frage. Für Lexart benutze ich dynamische Arrays, die ich mit setlength(feld,länge) dann einrichte.
Dabei fängt das Array dann bei feld[0] an und geht bis feld[länge-1].
Nun wäre es für mich besonders praktisch, wenn dieses Array bei -2 anfangen würde. Und etwa von feld[-2] bis feld[länge-3] geht.
Lässt sich das irgendwie einrichten? Mit statischen Arrays geht das ja, die kommen für das, was ich vor habe, aber nicht in Frage...
Also kurz, es wäre praktisch, wenn feld bei [-2] anfangen würde. Danke für die Antworten im Voraus!
Euklid
Habe wiedermal eine Frage. Für Lexart benutze ich dynamische Arrays, die ich mit setlength(feld,länge) dann einrichte.
Dabei fängt das Array dann bei feld[0] an und geht bis feld[länge-1].
Nun wäre es für mich besonders praktisch, wenn dieses Array bei -2 anfangen würde. Und etwa von feld[-2] bis feld[länge-3] geht.
Lässt sich das irgendwie einrichten? Mit statischen Arrays geht das ja, die kommen für das, was ich vor habe, aber nicht in Frage...
Also kurz, es wäre praktisch, wenn feld bei [-2] anfangen würde. Danke für die Antworten im Voraus!
Euklid
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
Das wird nicht gehen Euklid. Dynamische Arrays sind ein Zeiger auf einen Speicherraum, der kann schonmal nicht negativ sein. Das Äquivalent ist reservierter Speicher auf dem Heap mit New und Dispose. Vermutlich wird das Ganze auch so nachgebildet. Dabei werden die einzelnen Speicherbereiche nur durch Zeiger untereinander verknüpft. Also ist das 0te Element der Anchor und alle anderen Elemente enthalten predecessor und successor, was also nicht anderes als eine verkettete Liste darstellt.
Beim Anchor ist predecessor = nil, beim letzten Element successor = nil. Das dynamische Array stellt also nur die Zugriffsmöglichkeit über einen Index zur Verfügung, deswegen kann man wohl hinten anhängen, nicht aber vorne. Was man hierfür bräuchte wäre ein Ring, d.h. predecessor von Anchor ist das letzte Element, dann könnte man die Liste auch mit negativem Index rückwärts durchlaufen.
Aber warum will man das?
Beim Anchor ist predecessor = nil, beim letzten Element successor = nil. Das dynamische Array stellt also nur die Zugriffsmöglichkeit über einen Index zur Verfügung, deswegen kann man wohl hinten anhängen, nicht aber vorne. Was man hierfür bräuchte wäre ein Ring, d.h. predecessor von Anchor ist das letzte Element, dann könnte man die Liste auch mit negativem Index rückwärts durchlaufen.
Aber warum will man das?
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
-
- Lazarusforum e. V.
- Beiträge: 2808
- Registriert: Fr 22. Sep 2006, 10:38
- OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
- Wohnort: Hessen
- Kontaktdaten:
Ok, ist nicht so schlimm.
Nun, ich möchte für unser Computeralgebrasystem die Funktion einbauen, dass er z.B. im Binärsystem (und vielen anderen Zahlensystemen) rechnen kann. Das hätte ich durch einen Array of Integer realisiert.
Schön wäre es gewesen, wenn die in der eckigen Zahl stehenden Klammer gleich der Potenz der Zahl wäre. Dann wäre z.B.
11 = 1*2^0+1*2^1+0*2^2+1*2^3
abgespeichert als
feld[0]=1; feld[1]=1; feld[2]=0; feld[3]=1;
Da ich arbeitsspeicherbegrenzend große Zahlen zulassen möchte, brauche ich am Anfang des Arrays eine Information
1. über die höchste verwendete Potenz
2. über das zugrundeliegende Zahlensystem (binär, hexa, penta,...)
Das sind 2 Zusatzinformationen, die _vor_ der eigentlichen Zahl gespeichert werden müssen. Daher wäre es sehr praktisch gewesen, wenn das Array bei -2 beginnen hätte können.
So könnte ich die Sache z.B. mit einem Offset erledigen. Geht zwar auch, ist nur nicht so schön, wenn ich überall +2 hinzuschreiben muss. Die wird dann nämlich leicht vergessen, und er rechnet was verkehrtes...
... naja, danke für die Antwort!
Euklid
Nun, ich möchte für unser Computeralgebrasystem die Funktion einbauen, dass er z.B. im Binärsystem (und vielen anderen Zahlensystemen) rechnen kann. Das hätte ich durch einen Array of Integer realisiert.
Schön wäre es gewesen, wenn die in der eckigen Zahl stehenden Klammer gleich der Potenz der Zahl wäre. Dann wäre z.B.
11 = 1*2^0+1*2^1+0*2^2+1*2^3
abgespeichert als
feld[0]=1; feld[1]=1; feld[2]=0; feld[3]=1;
Da ich arbeitsspeicherbegrenzend große Zahlen zulassen möchte, brauche ich am Anfang des Arrays eine Information
1. über die höchste verwendete Potenz
2. über das zugrundeliegende Zahlensystem (binär, hexa, penta,...)
Das sind 2 Zusatzinformationen, die _vor_ der eigentlichen Zahl gespeichert werden müssen. Daher wäre es sehr praktisch gewesen, wenn das Array bei -2 beginnen hätte können.
So könnte ich die Sache z.B. mit einem Offset erledigen. Geht zwar auch, ist nur nicht so schön, wenn ich überall +2 hinzuschreiben muss. Die wird dann nämlich leicht vergessen, und er rechnet was verkehrtes...
... naja, danke für die Antwort!
Euklid
- af0815
- Lazarusforum e. V.
- Beiträge: 6856
- Registriert: So 7. Jan 2007, 10:20
- OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
- CPU-Target: 32Bit (64Bit)
- Wohnort: Burgenland
- Kontaktdaten:
Ansatz: Objekt überladen und mit eigenen Funktionen versehen. Dann kannst Du dir deinen negativen Index erzeugen. Und das +2 wird in das neue Objekt eingebettet.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
-
- Lazarusforum e. V.
- Beiträge: 7192
- Registriert: So 19. Nov 2006, 12:06
- OS, Lazarus, FPC: Linux Mint 19.3
- CPU-Target: AMD
- Wohnort: Oldenburg(Oldenburg)
Ich würde mir dafür eine eigene Liste anlegen:
Nimm z.b. eine Doppelt Verkette Liste.
Dann kannst du alles selbst machen.
Du müsstest auch bestimmen können wo die Liste anfängt;
dort start die Forschleife ja bei 0 wenn du jetzt bei -2 startest währe das auch kein Problem.
Wenn du möchtest kann ich ja meine unit hochladen.
Sie arbeitet so ähnlich wie eine TObjectlist halt nur mit eine "Doppelt Verketten Liste":
Löschen, insert, Add, updatet.clearall(alle Items auf einmal löschen) geht
Nimm z.b. eine Doppelt Verkette Liste.
Dann kannst du alles selbst machen.
Du müsstest auch bestimmen können wo die Liste anfängt;
Code: Alles auswählen
function TmyObjectList.GetMyListItem(Index: Integer): TObject;
var
i:Integer;
obj:TmyObjectListItem;
begin
if Index <=Count-1 then begin
// Optimierung: Damit nicht bei jeder anfrage
// Neu gesucht werden muss
if (oldItemindex > -1) and (index = oldItemIndex) then begin
obj:=oldObject;
end
else begin
obj:=First;
oldItemIndex:=index;
for i:=0 to index-1 do begin
if obj.nex <> NIL then
obj:=obj.nex;
end;
oldObject:=obj;
end;
FehlerIndex:=frNone;
result:=obj.inhalt;
end
else begin
if Count-1 > 0 then FehlerIndex:=frHihgIndex;
if Count-1 = 0 then FehlerIndex:=frClearList;
result:=niL;
end;
end;
Wenn du möchtest kann ich ja meine unit hochladen.
Sie arbeitet so ähnlich wie eine TObjectlist halt nur mit eine "Doppelt Verketten Liste":
Löschen, insert, Add, updatet.clearall(alle Items auf einmal löschen) geht
MFG
Michael Springwald
Michael Springwald
-
- Lazarusforum e. V.
- Beiträge: 2808
- Registriert: Fr 22. Sep 2006, 10:38
- OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
- Wohnort: Hessen
- Kontaktdaten:
Danke für die Anregungen! Werde das jetzt ein wenig tiefer durchdenken müssen, welche der vorgeschlagenen Methoden wohl die Geignetste ist.
Dynamische Arrays finde ich gerade in der Hinsicht wichtig, da sie den heap mitbenutzen. Angeblich ist ja der Stack auf 1 MB begrenzt. Siehe hierzu die Diskussion auf dieser Seite:
http://www.lazarusforum.de/viewtopic.ph ... light=heap" onclick="window.open(this.href);return false;
Mir kommt es darauf an, dass der Arbeitsspeicher bei unserem Programm wirklich die Grenze darstellt, und nicht irgendein Stack mit nur 1 MB Platz.
Dynamische Arrays finde ich gerade in der Hinsicht wichtig, da sie den heap mitbenutzen. Angeblich ist ja der Stack auf 1 MB begrenzt. Siehe hierzu die Diskussion auf dieser Seite:
http://www.lazarusforum.de/viewtopic.ph ... light=heap" onclick="window.open(this.href);return false;
Mir kommt es darauf an, dass der Arbeitsspeicher bei unserem Programm wirklich die Grenze darstellt, und nicht irgendein Stack mit nur 1 MB Platz.
-
- Lazarusforum e. V.
- Beiträge: 7192
- Registriert: So 19. Nov 2006, 12:06
- OS, Lazarus, FPC: Linux Mint 19.3
- CPU-Target: AMD
- Wohnort: Oldenburg(Oldenburg)
Wie viel Platzt würde denn belegt werden, bzw. wie groß würde dein Array denn werden ?
und soll dort gelöscht und hinzugefügt werden.
ich verstehe auch nicht ganz warum es -2 sein muss bzw. über haupt -.
von 0 bis unendlich müsste doch reichen ?
anderenseit könntest du es ja einfach so machen, das der index bis -2 runter gehen kann aber sobald du drauf zugreifst auf dein Array nimmst du ihn +2.
und soll dort gelöscht und hinzugefügt werden.
ich verstehe auch nicht ganz warum es -2 sein muss bzw. über haupt -.
von 0 bis unendlich müsste doch reichen ?
anderenseit könntest du es ja einfach so machen, das der index bis -2 runter gehen kann aber sobald du drauf zugreifst auf dein Array nimmst du ihn +2.
MFG
Michael Springwald
Michael Springwald
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
@Christian
Bei der verketteten List als Array angesprochen ist:
L[0] = Anchor, L[1] = Anchor.successor usw.
und damit wegen Anchor.succesor = nil sichergestellt das negativ nicht geht. Das funzt natürlich nur bei gleichen Objekten.
Deswegen würde ich Euklid zu einer entsprechenden Struktur raten, etwa so:
type
TMyStruct = class(Object)
suc,
pred: pointer;
Expo: integer; // kann auch beliebiger real sein
Zahl: double; // könnte auch pointer sein
public
// hier die Routinen beschreiben
end;
Dann kann man in Form eines Binärbaumes oder als Bubblesort die Liste sortieren. Dazu müssen jeweils nur suc(successor) und pred(predecessor) entsprechen umgehängt werden. Wurzel wäre dann:
a:= PtrList.GetZahl(-3);
wenn -3 der kleinste Index ist, mithin Anchor. Das ist weniger kompliziert als man glaubt und für mittelgroße Listen schnell erledigt. Hinzu kommt, das man auch unterschiedliche Zahlen benutzen kann, also cardinal oder extended, je nach Bedarf.
Bei der verketteten List als Array angesprochen ist:
L[0] = Anchor, L[1] = Anchor.successor usw.
und damit wegen Anchor.succesor = nil sichergestellt das negativ nicht geht. Das funzt natürlich nur bei gleichen Objekten.
Deswegen würde ich Euklid zu einer entsprechenden Struktur raten, etwa so:
type
TMyStruct = class(Object)
suc,
pred: pointer;
Expo: integer; // kann auch beliebiger real sein
Zahl: double; // könnte auch pointer sein
public
// hier die Routinen beschreiben
end;
Dann kann man in Form eines Binärbaumes oder als Bubblesort die Liste sortieren. Dazu müssen jeweils nur suc(successor) und pred(predecessor) entsprechen umgehängt werden. Wurzel wäre dann:
a:= PtrList.GetZahl(-3);
wenn -3 der kleinste Index ist, mithin Anchor. Das ist weniger kompliziert als man glaubt und für mittelgroße Listen schnell erledigt. Hinzu kommt, das man auch unterschiedliche Zahlen benutzen kann, also cardinal oder extended, je nach Bedarf.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
-
- Lazarusforum e. V.
- Beiträge: 2808
- Registriert: Fr 22. Sep 2006, 10:38
- OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
- Wohnort: Hessen
- Kontaktdaten:
Da ich eine exakte Rechnung unterstützen möchte, müssen die Zahlen beliebig genau gespeichert werden können. D.h., Das Array kann beliebig groß werden.pluto hat geschrieben:Wie viel Platzt würde denn belegt werden, bzw. wie groß würde dein Array denn werden ?
Neben den Zahlen (im Binärsystem: 010111000101001101010) soll am Anfang des Arrays noch eine Information über die großte verwendete Potenz (d.h. die Länge des Arrays) sowie über das verwendete Zahlensystem (im Beispiel das Binärsystem) enthalten.ich verstehe auch nicht ganz warum es -2 sein muss bzw. über haupt -.
von 0 bis unendlich müsste doch reichen ?
Von 0 bis unendlich würde reichen, jedoch nur mit einem Offset von +2. Das würde gehen, (ist wohl auch am Einfachsten), ist nur unschön und fehleranfällig.
-
- Lazarusforum e. V.
- Beiträge: 7192
- Registriert: So 19. Nov 2006, 12:06
- OS, Lazarus, FPC: Linux Mint 19.3
- CPU-Target: AMD
- Wohnort: Oldenburg(Oldenburg)
Du könntest doch einfach den ersten Eintrag überspringen und im Zweiten anfangen.
Baust dir ein Record:
test =record
size:Integer;
Welches:Zahlensystem
end;
und fertig.
ich hoffe du verstehst mich jetzt wie ich es meine.
Wobei die länge kannst du ganz leicht mit High oder Lengt ermitteln.
also brauchst du sie nicht zu speichern.
Baust dir ein Record:
test =record
size:Integer;
Welches:Zahlensystem
end;
und fertig.
ich hoffe du verstehst mich jetzt wie ich es meine.
Wobei die länge kannst du ganz leicht mit High oder Lengt ermitteln.
also brauchst du sie nicht zu speichern.
MFG
Michael Springwald
Michael Springwald
-
- Lazarusforum e. V.
- Beiträge: 2808
- Registriert: Fr 22. Sep 2006, 10:38
- OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
- Wohnort: Hessen
- Kontaktdaten:
Prima! Das ist zum einen mit keinen sonderlichen Aufwand verbunden, zum anderen erfüllt das den Zweck. Habe oben noch ein array hinzugefügt, und schon ist es perfekt. Dann brauche ich gar keine Arrays, die im Negativen anfangen. Hatte an den guten alten record garnicht gedachtpluto hat geschrieben:Baust dir ein Record:
test =record
Potenzfaktoren:array of cardinal;
size:Integer;
Welches:Zahlensystem
end;
und fertig.

Danke!
-
- Beiträge: 6079
- Registriert: Do 21. Sep 2006, 07:51
- OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
- CPU-Target: AVR,ARM,x86(-64)
- Wohnort: Dessau
- Kontaktdaten:
dnyamische arrays sind aber keine verkettete liste@Christian
Bei der verketteten List als Array angesprochen ist:
L[0] = Anchor, L[1] = Anchor.successor usw.
und damit wegen Anchor.succesor = nil sichergestellt das negativ nicht geht. Das funzt natürlich nur bei gleichen Objekten.
Deswegen würde ich Euklid zu einer entsprechenden Struktur raten, etwa so:
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/
-
- Beiträge: 1187
- Registriert: Mi 13. Dez 2006, 10:58
- OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
- CPU-Target: AMD A4-6400 APU
- Wohnort: Hamburg
@Euklid
Kleiner Tipp noch, es gibt auch die sogenannten varianten Records:
Achtung, die Namen der Variablen müssen sich unterscheiden wenn sie im case-Konstrukt auftauchen. Mit den Klammern mußt du nochmal nachsehen, so ähnlich ging das aber.
Für diese Strukturen wird immer der maximale Platz, also für die größte Struktur, reserviert. Mit ein paar Tricks kann man per:
auf den tatsächlichen Typ in der Puffervariablen Buf reagieren. Das kann dann auch ein Array oder sogar ein dynamisches Array sein. Die Struktur muß halt nur geschickt aufgebaut sein.
Kleiner Tipp noch, es gibt auch die sogenannten varianten Records:
Code: Alles auswählen
TMyRec = record
RecType: irgendein set;
case RecType of
myinteger: (integercontent: integer);
myreal :(realcontent: real;
realblabla: irgendwas);
end;
end;
Für diese Strukturen wird immer der maximale Platz, also für die größte Struktur, reserviert. Mit ein paar Tricks kann man per:
Code: Alles auswählen
procedure Tuwas(var Buf);
var
SetVar: irgendein set;
begin
move(Buf[0], SetVar, SizeOf(SetVar));
case SetVar of
myinteger: DoComputeMyInteger(Buf);
end; // of case
end;
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)