Delphi-PRAXiS
Seite 2 von 5     12 34     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Einheiten parsen (https://www.delphipraxis.net/184211-einheiten-parsen.html)

BUG 9. Mär 2015 13:11

AW: Einheiten parsen
 
Zitat:

Zitat von Jens01 (Beitrag 1292791)
Du meinst Grundeinheiten?: m, N, kg, s, ...

Genau das etwas meine ich (Basiseinheit) :stupid:
Im Prinzip könnte man so ein Einheitensystem auch anwendungspezifisch festlegen, aber es ist vermutlich clever SI-Einheiten zu benutzen. Die "zusammengesetzt Einheiten" sind nach der Terminologie dann abgeleite Einheiten.

Sir Rufo 9. Mär 2015 13:26

AW: Einheiten parsen
 
Ja, man kommt dann nicht drumherum diese Basiseinheiten mit allen ihren Ausprägungen (m, cm => 1/100m, km => 1000m, s, min => 60s, h => 3600s, ...) als Typ zu definieren.

Dann benötigt man einen weiteren Typen, der mit den zusammengesetzten Basiseinheiten umgehen kann. Da hat man dann Basis-Einheiten im Zähler und im Nenner, die man dann auch wegkürzen kann, damit aus
Code:
60 Meter/Sekunde * 60 Sekunden = 3600 Meter
werden kann.
Code:
Wert1 => Wert: 60, Einheit Zähler: [Meter], Einheit Nenner: [Sekunde]
Wert2 => Wert: 60, Einheit Zähler: [Sekunde], Einheit Nenner: []

Ergebnis => Wert 3600, Einheit Zähler: [Meter], Einheit Nenner: []
Spannend wird es dann eben noch, wenn man unterschiedliche Einheiten aus der gleichen Familie hat:
Code:
Wert1 => Wert: 60, Einheit Zähler: [KilometerMeter], Einheit Nenner: [Stunde]
Wert2 => Wert: 60, Einheit Zähler: [Sekunde], Einheit Nenner: []

Ergebnis => Wert 1, Einheit Zähler: [KiloMeter], Einheit Nenner: []

BUG 9. Mär 2015 14:23

AW: Einheiten parsen
 
Zitat:

Zitat von Sir Rufo (Beitrag 1292799)
mit allen ihren Ausprägungen als Typ zu definieren... unterschiedliche Einheiten aus der gleichen Familie hat

Eben nicht für alle möglichen Ausprägungen und keine unterschiedlichen Einheiten (im Typsystem) für die gleiche Größe.
Beim Einlesen werden alle Werte und Einheiten zu den Basiseinheiten normalisiert. Beim Ausgeben muss man gucken, wie die Anforderungen sind.

Bjoerk 9. Mär 2015 14:38

AW: Einheiten parsen
 
Kann man da nicht mit Sets oder irgendwie bitweise was rechen, sonst tippt man sich ja den Wolf? (und sind hier gerade mal 9 mögliche Kombinationen). Die usNone müssen natürlich noch ausgefüllt werden.

Delphi-Quellcode:

type
  TUnitStyle = (usNone, usKNdivM3, usKNdivM2, usKNdivM, usKNMdivM, usKNM, usKN, usM3, usM2, usM);

function GetUnitPlus(const A, B: TUnitStyle): TUnitStyle;
begin
  if A = B then
    Result := A
  else
    Result := usNone;
end;

function GetUnitMinus(const A, B: TUnitStyle): TUnitStyle;
begin
  if A = B then
    Result := A
  else
    Result := usNone;
end;

function GetUnitDiv(const A, B: TUnitStyle): TUnitStyle;
begin
  Result := usNone;
  case A of
    usKNdivM3:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKNdivM2:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKNdivM:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKNMdivM:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKNM:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKN:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usM3:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usM2:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usM:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
  end;
end;

function GetUnitMult(const A, B: TUnitStyle): TUnitStyle;
begin
  Result := usNone;
  case A of
    usKNdivM3:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKNdivM2:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKNdivM:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKNMdivM:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKNM:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usKN:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usM3:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usM2:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
    usM:
    begin
      case B of
        usKNdivM3:
          Result := usNone;
        usKNdivM2:
          Result := usNone;
        usKNdivM:
          Result := usNone;
        usKNMdivM:
          Result := usNone;
        usKNM:
          Result := usNone;
        usKN:
          Result := usNone;
        usM3:
          Result := usNone;
        usM2:
          Result := usNone;
        usM:
          Result := usNone;
      end;
    end;
  end;
end;

end.

BUG 9. Mär 2015 14:50

AW: Einheiten parsen
 
Zitat:

Zitat von Bjoerk (Beitrag 1292807)
Kann man da nicht mit Sets oder irgendwie bitweise was rechen, sonst tippt man sich ja den Wolf?

Deswegen reden wir ja über die Basiseinheiten und abgeleiteten Einheiten :mrgreen:
Zum Beispiel mit den Array aus Beitrag #9 lässt sich dass doch ganz komfortabel machen.

EDIT: Hast du das Ganze per Hand heruntergeschrieben? :pale:

Bjoerk 9. Mär 2015 14:56

AW: Einheiten parsen
 
Zitat:

Zitat von BUG (Beitrag 1292810)
EDIT: Hast du das Ganze per Hand heruntergeschrieben? :pale:

Nee. Aber selbst das kopieren war schon Arbeit :)

Deinen Ansatz #9 hab ich nich kapiert. Montags kapier ich noch weniger als sonst.. Kannst nochmal etwas erläutern?

BUG 9. Mär 2015 16:28

AW: Einheiten parsen
 
Deine Basiseinheiten definierst du weiter als Aufzählungstyp:
Delphi-Quellcode:
type
  TFundamentalUnit = (fuKN, fuM);
Die zusammengesetzten Einheiten lassen sich auch in Exponentenschreibweise aufschreiben. Die Exponenten kannst du dann einfach in einem Array speichern.
Delphi-Quellcode:
type
  TDerivedUnit = array[fuKN..fuM] of Integer.
TUnitStyle Exponentenschreibweise Arrayinhalt
usNone kN^0 * m^0 0, 0
usKNdivM3 kN^1 * m^(-3) 1, -3
usKNM kN^1 * m^1 1, 1
sKN kN^1 * m^0 1, 0
usM3 kN^0 * m^3 0, 3

Zum Beispiel die Multiplikation kann man nun ganz einfach auf eine Addition der Array-Einträge abbilden (quasi mit den Rechenregeln für Potenzen):
  1. usM3 * usKNdivM2
  2. (kN^0 * m^3) * (kN^1 * m^(-2))
  3. (kN^(0+1) * m^(3-2)
  4. kN^1 * m^1
  5. usKNM :thumb:

Ich hoffe das ist verständlicher :wink:

Bjoerk 9. Mär 2015 20:03

AW: Einheiten parsen
 
Geht sehr gut. Danke Robert. :thumb:

Delphi-Quellcode:
type
  TUnitBase = (fuKN, fuM);
  TUnitStyle = (usNone, usKNdivM3, usKNdivM2, usKNdivM, usKNM, usKN, usM3, usM2, usM);

  TUnits = class
  private
    FItems: array[usNone..usM, fuKN..fuM] of integer;
    function GetValues(Index: TUnitStyle): double;
    function GetAsString(Index: TUnitStyle): string;
  public
    property Values[Index: TUnitStyle]: double read GetValues;
    property AsString[Index: TUnitStyle]: string read GetAsString;
    function GetPlus(const A, B: TUnitStyle): TUnitStyle;
    function GetMinus(const A, B: TUnitStyle): TUnitStyle;
    function GetDiv(const A, B: TUnitStyle): TUnitStyle;
    function GetMult(const A, B: TUnitStyle): TUnitStyle;
    constructor Create;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TUnits }

constructor TUnits.Create;
begin
  FItems[usNone, fuKN] := 0;
  FItems[usNone, fuM] := 0;

  FItems[usKNdivM3, fuKN] := 1;
  FItems[usKNdivM3, fuM] := -3;

  FItems[usKNdivM2, fuKN] := 1;
  FItems[usKNdivM2, fuM] := -2;

  FItems[usKNdivM, fuKN] := 1;
  FItems[usKNdivM, fuM] := -1;

  FItems[usKNM, fuKN] := 1;
  FItems[usKNM, fuM] := 1;

  FItems[usKN, fuKN] := 1;
  FItems[usKN, fuM] := 0;

  FItems[usM3, fuKN] := 0;
  FItems[usM3, fuM] := 3;

  FItems[usM2, fuKN] := 0;
  FItems[usM2, fuM] := 2;

  FItems[usM, fuKN] := 0;
  FItems[usM, fuM] := 1;
end;

function TUnits.GetValues(Index: TUnitStyle): double;
begin
  Result := IntPower(FItems[Index, fuKN], FItems[Index, fuM]);
end;

function TUnits.GetAsString(Index: TUnitStyle): string;
begin
  case Index of
    usKNdivM3:
      Result := 'kN/m3';
    usKNdivM2:
      Result := 'kN/m2';
    usKNdivM:
      Result := 'kN/m';
    usKNM:
      Result := 'kNm';
    usKN:
      Result := 'kN';
    usM3:
      Result := 'm3';
    usM2:
      Result := 'm2';
    usM:
      Result := 'm';
    else
      Result := '';
  end;
end;

function TUnits.GetPlus(const A, B: TUnitStyle): TUnitStyle;
begin
  if A = B then
    Result := A
  else
    Result := usNone;
end;

function TUnits.GetMinus(const A, B: TUnitStyle): TUnitStyle;
begin
  if A = B then
    Result := A
  else
    Result := usNone;
end;

function TUnits.GetMult(const A, B: TUnitStyle): TUnitStyle;
var
  I: TUnitStyle;
  KN, M: integer;
begin
  Result := usNone;
  KN := FItems[A, fuKN] + FItems[B, fuKN];
  M := FItems[A, fuM] + FItems[B, fuM];
  for I := Low(TUnitStyle) to High(TUnitStyle) do
    if (KN = FItems[I, fuKN]) and (M = FItems[I, fuM]) then
    begin
      Result := I;
      Break;
    end;
end;

function TUnits.GetDiv(const A, B: TUnitStyle): TUnitStyle;
var
  I: TUnitStyle;
  KN, M: integer;
begin
  Result := usNone;
  KN := FItems[A, fuKN] - FItems[B, fuKN];
  M := FItems[A, fuM] - FItems[B, fuM];
  for I := Low(TUnitStyle) to High(TUnitStyle) do
    if (KN = FItems[I, fuKN]) and (M = FItems[I, fuM]) then
    begin
      Result := I;
      Break;
    end;
end;

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  Units: TUnits;
  A, B, C: TUnitStyle;
begin
  Units := TUnits.Create;
  try
    A := usM3;
    B := usKNdivM2;
    C := Units.GetMult(A, B);
    ShowMessage(Units.AsString[C]);
    A := usKN;
    B := usM;
    C := Units.GetDiv(A, B);
    ShowMessage(Units.AsString[C]);
  finally
    Units.Free;
  end;
end;

Sailor 9. Mär 2015 21:18

AW: Einheiten parsen
 
Und warum nicht einen stinknormalen Expression-Parser um Einheiten erweitern und die Umrechnung in die Semantikroutinen legen? Hätte auch noch den Vorteil einer komfortablen Fehlerbehandlung.

Bjoerk 9. Mär 2015 21:50

AW: Einheiten parsen
 
Wenn du uns noch kurz sagst wo hier eine Exception auftreten kann? :wink:


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:07 Uhr.
Seite 2 von 5     12 34     Letzte »    

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