Dynamische Arrays - ins negative Erweiterbar?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Euklid
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?

Beitrag von Euklid »

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

schnullerbacke
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

Beitrag von schnullerbacke »

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?
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Euklid
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:

Beitrag von Euklid »

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

Benutzeravatar
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:

Beitrag von af0815 »

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).

pluto
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)

Beitrag von pluto »

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;

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;
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
MFG
Michael Springwald

Christian
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:

Beitrag von Christian »

Hat das mal einer ausprobiert ? Also mir leuchtet schnullers Erklärung nicht ein da der Index ja nichts mit dem Zeiger zu tun hat. Es ist nur ein Index ...
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Euklid
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:

Beitrag von Euklid »

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.

pluto
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)

Beitrag von pluto »

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.
MFG
Michael Springwald

schnullerbacke
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

Beitrag von schnullerbacke »

@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.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Euklid
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:

Beitrag von Euklid »

pluto hat geschrieben:Wie viel Platzt würde denn belegt werden, bzw. wie groß würde dein Array denn werden ?
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.
ich verstehe auch nicht ganz warum es -2 sein muss bzw. über haupt -.
von 0 bis unendlich müsste doch reichen ?
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.

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.

pluto
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)

Beitrag von pluto »

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.
MFG
Michael Springwald

Euklid
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:

Beitrag von Euklid »

pluto hat geschrieben:Baust dir ein Record:
test =record
Potenzfaktoren:array of cardinal;
size:Integer;
Welches:Zahlensystem
end;
und fertig.
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 gedacht :D
Danke!

pluto
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)

Beitrag von pluto »

Kannst ja auch eine Klasse nutzen. Das spielt ja keine rolle !
MFG
Michael Springwald

Christian
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:

Beitrag von Christian »

@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:
dnyamische arrays sind aber keine verkettete liste
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

schnullerbacke
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

Beitrag von schnullerbacke »

@Euklid

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;
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:

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;
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.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Antworten