Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Dyn. Array of Double an funktion übergeben (https://www.delphipraxis.net/207421-dyn-array-double-funktion-uebergeben.html)

wendelin 22. Mär 2021 18:31

Dyn. Array of Double an funktion übergeben
 
Hallo,
ich suchte vor einiger Zeit nach einer Funktion ähnlich der function MaxIntValue.
Nur für Real-Zahlen! Übergeben wollte ich ein Dyn. Array.

Also so etwas wie MaxFloatValue(Array of Double). Gibt es aber nicht.
Nun habe ich bei 'StackOverflow' eine Ersatzfunktion gefunden :
Delphi-Quellcode:
uses
  Math; // MaxDouble is defined by this unit

function IndexOfMaxValue(const x: array of Double): Integer;
var
  Index: Integer;
  MaxValue: Double;
begin
  Result := -1;
  MaxValue := -MaxDouble;
  for Index := 0 to high(x) do begin
    if x[Index]>MaxValue then begin
      Result := Index;
      MaxValue := x[Index];
    end;
  end;
end;
Diese funktioniert aber nicht.Es gibt diverse Fehlermeldungen
Wie muß ich o.g. function aufrufen ?

Wendelin

KodeZwerg 22. Mär 2021 18:44

AW: Dyn. Array of Double an funktion übergeben
 
Was für Fehler erscheinen denn?
Aufrufen indem man ein array of double übergibt, als ergebnis kommt der index vom höchstwert raus.

KodeZwerg 22. Mär 2021 19:03

AW: Dyn. Array of Double an funktion übergeben
 
Delphi-Quellcode:
program Project7;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

function GetMaxDoubleArrayIndex(const DoubleArray: array of Double): Integer;
var
  i: Integer;
  highest: Double;
begin
  Result := -1;
  highest := Low(Integer);
  for i := Low(DoubleArray) to High(DoubleArray) do
    if DoubleArray[i] > highest then
      begin
        Result := i;
        highest := DoubleArray[i];
      end;
end;

var
  TestArray: array of Double;
  i: Integer;
begin
  try
    Randomize;
    SetLength(TestArray, 8);
    for i := Low(TestArray) to High(TestArray) do
      TestArray[i] := Random(100000);
    for i := Low(TestArray) to High(TestArray) do
      WriteLn('#' + IntToStr(i) + ' = ' + FloatToStr(TestArray[i]));
    WriteLn;
    WriteLn('Höchstwert hat Index #' + IntToStr(GetMaxDoubleArrayIndex(TestArray)));
    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
kurz mal geschrieben, scheint zu funktionieren.

Andreas13 22. Mär 2021 19:46

AW: Dyn. Array of Double an funktion übergeben
 
Wendelin wollte dynamische Arrays übergeben. KodeZwerg's
Delphi-Quellcode:
TestArray: Array[0..8] of Double;
ist aber ein statisches Array.
Ohne Deine Fehlermeldungen ist es schwer zu sagen, woran der ursprüngliche Fehler liegt, ich vermute jedoch, daß das dynamische Array nicht initialisiert worden ist.
Wahrscheinlich fehlt
Delphi-Quellcode:
  ...
  SetLength(X_Array, Len);
Gruß, Andreas

Zeig doch mal Deinen Code, wo Du das dynamische Array übergibst, dann können wir Dir besser helfen.

KodeZwerg 22. Mär 2021 20:06

AW: Dyn. Array of Double an funktion übergeben
 
Zitat:

Zitat von Andreas13 (Beitrag 1485787)
Wendelin wollte dynamische Arrays übergeben.

(Ich sehe da keinen Unterschied aber dem sei so.)

Dann hatte ich da was falsch Verstanden und das Snippet ist nun entsprechend angepasst.

Danke das Du mich darauf Aufmerksam gemacht hast!

Andreas13 22. Mär 2021 20:57

AW: Dyn. Array of Double an funktion übergeben
 
Deine Funktion
Delphi-Quellcode:
function GetMaxDoubleArrayIndex(const DoubleArray: array of Double): Integer;
hat einen sogenannten offenen Array-Parameter, der sowohl statische, wie auch dynamische Arrays "schluckt".
Gruß, Andreas

Andreas13 22. Mär 2021 21:01

AW: Dyn. Array of Double an funktion übergeben
 
Die "Gefahr" bei offenen Parametern besteht nur darin, daß der Index sowohl bei 0 (dynamisch), als auch bei 1 (statisch) beginnen kann. Daher sollte der Zugriff immer über Low(..) und High(..) erfolgen, wenn man nicht total durcheinanderkommen will.
Andreas

KodeZwerg 22. Mär 2021 22:06

AW: Dyn. Array of Double an funktion übergeben
 
Zitat:

Zitat von Andreas13 (Beitrag 1485791)
Die "Gefahr" bei offenen Parametern besteht nur darin, daß der Index sowohl bei 0 (dynamisch), als auch bei 1 (statisch) beginnen kann. Daher sollte der Zugriff immer über Low(..) und High(..) erfolgen, wenn man nicht total durcheinanderkommen will.
Andreas

Jo, ist mir vorhin beim updaten auch eingefallen. :thumb:

TomyN 23. Mär 2021 08:21

AW: Dyn. Array of Double an funktion übergeben
 
Du kannst auch einen entsprechenden Typ definieren

Code:
Type
TAD: array of double;

...

function Mach_Was_Draus(daten_array: TAD): Integer;

himitsu 23. Mär 2021 08:30

AW: Dyn. Array of Double an funktion übergeben
 
Sowas ginge inzwischen (seit 12 Jahren) auch generisch.
Delphi-Quellcode:
function Mach_Was_Draus(daten_array: TArray<Double>): Integer;

DeddyH 23. Mär 2021 08:36

AW: Dyn. Array of Double an funktion übergeben
 
Nur mal als Anregung:
Delphi-Quellcode:
function MaxFloatValue(const Values: array of double): double;
var
  i: integer;
begin
  if Length(Values) < 1 then
    raise Exception.Create('Keine Vergleichswerte übergeben');
  Result := Values[Low(Values)];
  for i := Low(Values) + 1 to High(Values) do
    if Values[i] > Result then
      Result := Values[i];
end;

dummzeuch 23. Mär 2021 09:43

AW: Dyn. Array of Double an funktion übergeben
 
Zitat:

Zitat von DeddyH (Beitrag 1485811)
Nur mal als Anregung:
Delphi-Quellcode:
function MaxFloatValue(const Values: array of double): double;
var
  i: integer;
begin
  if Length(Values) < 1 then
    raise Exception.Create('Keine Vergleichswerte übergeben');
  Result := Values[Low(Values)];
  for i := Low(Values) + 1 to High(Values) do
    if Values[i] > Result then
      Result := Values[i];
end;

Oder, wenn's leichter zu lesen sein soll:

Delphi-Quellcode:
function MaxFloatValue(const Values: array of double): double;
var
  i: integer;
  Len: integer;
begin
  Len := Length(Values)
  if Len < 1 then
    raise Exception.Create('Keine Vergleichswerte übergeben');
  Result := Values[0];
  for i := 1 to Len - 1 do
    if Values[i] > Result then
      Result := Values[i];
end;
Denn: Innerhalb der Funktion ist Low() immer 0 und High() immer Length()-1.

Um nochmal Rudy zu Wort kommen zu lassen:
http://rvelthuis.de/articles/articles-openarr.html

himitsu 23. Mär 2021 09:56

AW: Dyn. Array of Double an funktion übergeben
 
Wurde nicht vorhin noch der Index geliefert?
Jetzt das Max.

Der Compiler sollte aus Low(Values) eine konstante 0 machen,
also im Compilat gibt es keinen Unterschied zwischen Low(Values) und 0.

Eine Lösung für 10.4.2
Delphi-Quellcode:
function MaxFloatValue(const Values: array of Double): Double;
begin
  if Length(Values) = 0 then
    Exit(0); // oder eine Exception
  Result := Values[0]; // oder eben Result := Values[Low(Values)];
  for var Value in Values do
    if Value > Result then
      Result := Value;
end;
und noch was für alle Delphis/FreePascal/...
Delphi-Quellcode:
function MaxFloatValue(const Values: array of Double): Double;
begin
  if Length(Values) = 0 then
    Exit(0); // oder eine Exception
  Result := MaxValue(Values);
end;

Zitat:

Zitat von System.Math.pas
Delphi-Quellcode:
function MaxValue(const Data: array of Single): Single;
var
  I: Integer;
begin
  Result := Data[Low(Data)];
  for I := Low(Data) + 1 to High(Data) do
    if Result < Data[I] then
      Result := Data[I];
end;


TomyN 23. Mär 2021 13:36

AW: Dyn. Array of Double an funktion übergeben
 
Auch wenn ich weiß, dass der Compiler es automatisch macht, so schreibe ich persönlich doch lieber

Code:
function MaxValue(const Data: array of Single): Single;
var
  I: Integer;
  startL: Integer;
  endL: Integer;
begin
  Result := Data[Low(Data)];
  startL:= Succ(Low(Data));
  endL:= High(Data);
  for I := startL to endL do
    if Result < Data[I] then
      Result := Data[I];
end;
Und ob max absolut sein soll oder nicht, wäre noch zu klären.

Tomy

wendelin 24. Mär 2021 10:44

AW: Dyn. Array of Double an funktion übergeben
 
Hallo,
vielen Dank für Eure Antworten.

Die Fehlermedung 'Incompatible Types' Array und dyn. Array kam von einer falschen Array-Var.
Jetzt läuft es!

Ich habe noch eine Frage: Warum muß im Funktionskopf das Array of Double als Konstante deklariert werden ?

Ich habe noch die Funktion IndexOfMinValue geschrieben:
Delphi-Quellcode:
function IndexOfMinValue_1(Const x : Array of Double): Integer;
Var
  Index   : Integer;
  MinValue : Double;
begin
  Result  := high(x);
  MinValue := MaxDouble;
  for Index := 0 to high(x) do begin
    if x[Index] < MinValue then begin
      Result := Index;
      MinValue := x[Index];
    end;
  end;
end;
Wendelin

Andreas13 24. Mär 2021 10:57

AW: Dyn. Array of Double an funktion übergeben
 
CONST im Funktionskopf sorgt dafür, daß
- ein Pointer auf das Array übergeben wird und nicht der Inhalt des Arrays kopiert wird,
- das Original-Array nicht verändert werden kann
- das Ablegen des Arrays im Speicher vom Compiler optimiert werden kann, um effizientere Zugriffe zu ermöglichen.

Möglicherweise gibt es noch mehr Gründe, die unsere Top-Spezialisten Dir besser erklären können.
Gruß, Andreas

wendelin 24. Mär 2021 11:34

AW: Dyn. Array of Double an funktion übergeben
 
Danke Andreas,

Gruß Wendelin

Andreas13 24. Mär 2021 12:16

AW: Dyn. Array of Double an funktion übergeben
 
Viel Efolg, Wendelin !:-D
Gruß, Andreas

Andreas13 24. Mär 2021 16:17

AW: Dyn. Array of Double an funktion übergeben
 
Hallo Wendelin,
noch ein kleiner Tipp: Wenn Delphi 7 Enterprise noch kein CONST im Funktionskopf kennt, Du solltest stattdessen überall VAR benutzen.
Gruß, Andreas

Stevie 24. Mär 2021 23:00

AW: Dyn. Array of Double an funktion übergeben
 
Zitat:

Zitat von Andreas13 (Beitrag 1485791)
Die "Gefahr" bei offenen Parametern besteht nur darin, daß der Index sowohl bei 0 (dynamisch), als auch bei 1 (statisch) beginnen kann. Daher sollte der Zugriff immer über Low(..) und High(..) erfolgen, wenn man nicht total durcheinanderkommen will.
Andreas

Sorry, aber das ist leider falsch - ein open array parameter besteht aus dem Pointer aufs erste Element und den letzten index.

Zitat:

Zitat von Dokumentation
Sie sind stets nullbasiert.


Delphi-Quellcode:
for i := 0 to High(values)
ist somit immer korrekt.
Kannste auch im disassembly angucken, aus
Delphi-Quellcode:
Low(values)
wird immer stumpf hardcoded 0.

Und deshalb geht damit auch sowas schickes.

KodeZwerg 24. Mär 2021 23:39

AW: Dyn. Array of Double an funktion übergeben
 
TestArray[1..2]: Array of Byte;
...
WriteLn(TestArray[0]);

kann das funktionieren?

Andreas13 25. Mär 2021 00:09

AW: Dyn. Array of Double an funktion übergeben
 
Hallo Stefan,
mit "Gefahr" habe ich folgende Situation gemeint:
Delphi-Quellcode:
program Offene_Array_Parameter_1;
{$APPTYPE CONSOLE}
{$R *.res}
Procedure Print_Vektor(CONST Vektor: Array of Integer; Name: String); overload;
VAR
  Zeile: Integer;

Begin
  WriteLn(Name, ':');
  For Zeile:= Low(Vektor) To High(Vektor) Do
  Begin
    WriteLn('Vektor[', Zeile,'] = ', Vektor[Zeile]);
  End;
  WriteLn;
End;

Procedure Print_Vektor(CONST Vektor: Array of Integer; Zeile: Integer; Name: String); overload;

Begin
  WriteLn(Name, ':');
  WriteLn('Vektor[', Zeile,'] = ', Vektor[Zeile]);
  WriteLn;
End;

CONST
  Len = 8;

VAR
  Statischer_Vektor : Array[1..Len] of Integer;
  Dynamischer_Vektor: Array of Integer;

  i, Pos: Integer;
 
Begin
    SetLength(Dynamischer_Vektor, Len);

    Try  
      For i:= Low(Dynamischer_Vektor) To High(Dynamischer_Vektor) Do
      Begin
        Dynamischer_Vektor[i]:= i;    
      End;

      For i:= 1 To Len Do
      Begin
        Statischer_Vektor[i]:= i;    
      End;
           
      Print_Vektor(Dynamischer_Vektor, 'Dynamischer_Vektor');
      Print_Vektor(Statischer_Vektor,  'Statischer_Vektor');
      WriteLn;
     
      Pos:= 2;
      WriteLn(Pos, '-tes Element durcken:');
      WriteLn;
     
      Print_Vektor(Dynamischer_Vektor, Pos, 'Dynamischer_Vektor');
      Print_Vektor(Statischer_Vektor, Pos, 'Statischer_Vektor --> FALSCH');
     
      ReadLn;
   
    Finally
      Dynamischer_Vektor:= NIL;
    End;
  End.
Gruß, Andreas

Stevie 25. Mär 2021 00:56

AW: Dyn. Array of Double an funktion übergeben
 
Zitat:

Zitat von KodeZwerg (Beitrag 1485991)
TestArray[1..2]: Array of Byte;
...
WriteLn(TestArray[0]);

kann das funktionieren?

Die Rede ist von open array parametern und nicht von statischen arrays - logisch, dass das da out of bounds ist - war das ne Fangfrage? :roll:

Zitat:

Zitat von Andreas13 (Beitrag 1485992)
mit "Gefahr" habe ich folgende Situation gemeint

Den base index einer Range vermischen ist immer eine Gefahr - ändert aber nix daran, dass open array zero based ist.
Wenn ich also von einer Funktion, die ein open array entgegen nimmt, einen Index für ein übergebenes n-based array geliefert bekomme, oder übergebe, muss ich da zwischen 0 und n umrechnen, da ändert auch nen Low/High innerhalb der Funktion nix.

KodeZwerg 25. Mär 2021 01:59

AW: Dyn. Array of Double an funktion übergeben
 
Zitat:

Zitat von Stevie (Beitrag 1485996)
Zitat:

Zitat von KodeZwerg (Beitrag 1485991)
TestArray[1..2]: Array of Byte;
...
WriteLn(TestArray[0]);

kann das funktionieren?

Die Rede ist von open array parametern und nicht von statischen arrays - logisch, dass das da out of bounds ist - war das ne Fangfrage? :roll:

Ist nicht out of bound, ist schlichtweg völlig verkehrte Syntax.
Es würde nicht mal ansatzweise funktionieren da ich die Klammern verkehrt gesetzt hab, hätte als Antwort kommen müssen.
Aber ja ich weiß was Du meintest obwohl ich nen dynamisches array abgebildet habe.

Stevie 25. Mär 2021 02:25

AW: Dyn. Array of Double an funktion übergeben
 
Zitat:

Zitat von KodeZwerg (Beitrag 1485999)
ist schlichtweg völlig verkehrte Syntax.

Hab schon Autokorrektur beim Lesen, da so viele Leute defekten Pseudocode schreiben.
Offensichtlich funktioniert die auch nicht fehlerfrei. :mrgreen:

Andreas13 25. Mär 2021 09:31

AW: Dyn. Array of Double an funktion übergeben
 
Hi Stefan,
mit "Gefahr" habe ich ganz konkret gemeint: Finger weg von "Open Array-Parametern", sondern den Array-Type immer explizit deklarieren, damit gar nicht so ein Chaos entstehen kann.
Gruß, Andreas


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:54 Uhr.

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