Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Array SCHNELL auf Null setzen (https://www.delphipraxis.net/182371-array-schnell-auf-null-setzen.html)

Dejan Vu 21. Okt 2014 04:13

AW: Array SCHNELL auf Null setzen
 
Also wie sieht denn nun der Code aus, um ein
Delphi-Quellcode:
array of array of integer
zu füllen?
Spontan:
Delphi-Quellcode:
Procedure ZeroDynamicMatrix (aMatrix : TMatrix; rows, cols : Integer);
var
  i : Integer;
  NumberOfBytesPerRow : Integer;

Begin
  setLength(aMatrix,rows);
  NumberOfBytesPerRow := cols*sizeof(aMatrix[0][0]); // sollte gehen, da compile time constant.
  for i:=0 to cols-1 do begin
    setLength(aMatrix[i], cols);
    FillChar(aMatrix[i][0], NumberOfBytesPerRow);
  end;
end;
Optimierungsvorschläge?

Namenloser 21. Okt 2014 05:06

AW: Array SCHNELL auf Null setzen
 
Was man noch machen kann, wenn das Array immer „rechteckig“ ist, ist, kein Array of Array zu nehmen, sondern den ganzen Speicherbereich am Stück anzufordern, und dann den Index von Hand (bzw. über entsprechende Getter und Setter) auszurechnen.

Statt:
Delphi-Quellcode:
var a: array of array of integer;

SetLength(a, rows);

for i := 0 to rows - 1 do
  SetLength(a[i], cols);
So:
Delphi-Quellcode:
var a: array of integer;

SetLength(a, rows*cols);
a[y,x] im ersten Beispiel entspricht dann a[y*cols + x] im zweiten Beispiel. Dadurch spart man erstens die Pointer-Dereferenzierungen auf der ersten Ebene, und außerdem ist der Zugriff auf die Elemente cacheeffizienter, weil es zwischendrin keine Lücken gibt. Beim naiven Ansatz könnte der Speichermanager die Unterarrays sonstwohin verstreuen.

Außerdem kann man das ganze Array dann mit einem einzigen Aufruf von FillChar nullen und braucht dazu keine äußere Schleife mehr.

samso 21. Okt 2014 06:47

AW: Array SCHNELL auf Null setzen
 
Nach meinem Kenntnisstand ist der Delphi-Compiler intelligent genug um gleichförmige Arrays zu erkennen.
Statt:
Code:
for i := 0 to rows - 1 do
   SetLength(a[i], cols);
formuliert man

Code:
SetLength(a, rows, cols);
Edit 1: Sorry, ich habe übersehen, dass das ja schon in #2 stand.
Edit 2: Leider ist der Compiler anscheinend doch zu doof. :-( ich bin frustriert. Vielleicht hätte ich bei Assembler bleiben sollen...

Stevie 21. Okt 2014 07:42

AW: Array SCHNELL auf Null setzen
 
Was soll daran doof sein? Ein gleichförmiges zweidimensionales Array ist numal kein eindimensionales Array, obwohl man es als solches implementieren kann.
Und dann auch nur so weit, wie ich sichergehen kann, dass man nicht noch nachträglich eine Dimension verändert (dynamisch und so...)

greenmile 21. Okt 2014 08:10

AW: Array SCHNELL auf Null setzen
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1276656)
Zitat:

Zitat von Blup (Beitrag 1276655)
Beim Initialisieren wird das Array nicht mit Nullen gefüllt.

Das ist schlichtweg falsch!

Delphi-Quellcode:
SetLength
ruft intern
Delphi-Quellcode:
DynArraySetLength
aus System.pas auf. Dort steht dann (in XE7 Zeile 33931-33933) folgender Code:

Delphi-Quellcode:
  // Set the new memory to all zero bits
  if newLength > oldLength then
    FillChar((PByte(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0);

Cool, das ist gut zu wissen. So wie jede Variable initialisiere ich bisher jedes Array.

samso 21. Okt 2014 08:16

AW: Array SCHNELL auf Null setzen
 
@Stevie:
Vielleicht war meine Formulierung zu hart. Ich hätte auch sagen können: Leider ist der Compiler nicht so schlau ein gleichförmiges mehrdimensionales dynamisches Array anders zu behandeln als ein ungleichförmiges mehrdimensionales dynamisches Array. Ohne dies jemals zu prüfen, ging ich bisher davon aus, dass die Sequenz
Code:
a: array of array of Integer;
etwas anderes wäre als
Code:
a: array of TIntegerDynArray;
Ich habe jetzt gelernt: Sofern die Darstellung des Arrays im Speicher eine Rolle spielt, muss der Programmierer ein gleichförmiges mehrdimensionales dynamisches Array selbst verwalten (wie in #12 gezeigt).

Uwe Raabe 21. Okt 2014 08:59

AW: Array SCHNELL auf Null setzen
 
Zitat:

Zitat von Dejan Vu (Beitrag 1276767)
Also wie sieht denn nun der Code aus, um ein
Delphi-Quellcode:
array of array of integer
zu füllen?

Wie schon erwähnt, ruft SetLength intern DynArraySetLength auf. Diese Methode ist rekursiv und arbeitet auch mit mehrdimensionalen Arrays. Ein
Delphi-Quellcode:
arr: array of array of Integer
wird also mit einem Aufruf von
Delphi-Quellcode:
SetLength(arr, 10, 20)
ebenso mit Nullen initialisiert wie ein eindimensionales.

hoika 21. Okt 2014 09:00

AW: Array SCHNELL auf Null setzen
 
Hallo,

also ich verlasse mich nicht auf automatisches Setzen des Compilers.
Da wir Datenbankprogramme entwickeln,
spielt der Overhead des Initialisierens hier überhaupt keine Rolle.

Heiko

Uwe Raabe 21. Okt 2014 09:04

AW: Array SCHNELL auf Null setzen
 
Zitat:

Zitat von hoika (Beitrag 1276777)
also ich verlasse mich nicht auf automatisches Setzen des Compilers.

Ist ja nicht direkt der Compiler, sondern die entsprechende Prozedur der RTL. Aber wie du meinst.

p80286 21. Okt 2014 10:27

AW: Array SCHNELL auf Null setzen
 
Zitat:

Zitat von hoika (Beitrag 1276777)
Hallo,

also ich verlasse mich nicht auf automatisches Setzen des Compilers.

Da kann ich nur zustimmen, auch wenn ich das gleiche wie ... mache, dann steht's in meinen Sourcen, in 5 Jahren weiß doch keiner mehr ob XE2 dreidimensionale arrays mit 0 initialisiert hat oder ob nicht.

Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:01 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz