Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Float Zahlen in Hex Zahlen umwandeln (https://www.delphipraxis.net/177913-float-zahlen-hex-zahlen-umwandeln.html)

satfer 5. Dez 2013 11:06

Float Zahlen in Hex Zahlen umwandeln
 
Hallo Leute,

ich hab folgendes Problem. Ich steuere einen Schunk Servogreifer per Profibus an und muss
die Parameter in Hex übertragen. Dass Problem ist, es muss eine float-hex umwandlung sein sonst akzeptiert
der Greifer die Parameter nicht. Ich hab jetzt lang genug gesucht und nix gefunden.
Kann mir da jemand weiterhelfen?

Umwandlung Float zu Hex

Der schöne Günther 5. Dez 2013 11:23

AW: Float Zahlen in Hex Zahlen umwandeln
 
Profibus habe ich bislang immer erfolgreich vor mir her geschoben, kenne mich damit also nicht aus. Wie will er die Fließkommazahlen haben? Einfach die Bytes nach IEEE 754-Notation in Hex-Form?

Beispielsweise so?

Delphi-Quellcode:
procedure TForm5.FormCreate(Sender: TObject);
var
   float: Single;
   byteNo: Integer;
begin

   float := System.Pi();

   self.Caption := float.ToString()+'=';
   for byteNo := 0 to Pred(float.Size()) do
      self.Caption := self.Caption + float.Bytes[byteNo].ToHexString(2);

end;
Oder Mantisse, Exponent usw. einzeln in Hex-Schreibweise übertragen?


Was von den Java-ähnlichen Typenhelfern wie (3.14.toString()) in Delphi 7 schon ging weiß ich nicht.
Delphi-Quellcode:
System.TSingleRec
scheint ein paar Helfermethoden für Gleitkommazahlen zu haben...


Oh und Herzlich Willkommen in den Heiligen Hallen des Wissens und des Wahnsinns :hi::corky:

Darlo 5. Dez 2013 11:23

AW: Float Zahlen in Hex Zahlen umwandeln
 
Hi,

kann ja sein, dass ich jetzt komplett daneben liege, aber meines Wissens sind Hex-Zahlen nur Integer.....

Sollte ich hier richtig liegen dann macht es Sinn, dass es
Delphi-Quellcode:
IntToHex()
gibt aber kein
Delphi-Quellcode:
FloatToHex()
;-)

gammatester 5. Dez 2013 11:36

AW: Float Zahlen in Hex Zahlen umwandeln
 
Single belegen vier Bytes. Ich nehme an, daß diese 4 Bytes als $xx, $xx, $xx, $xx übertragen werden sollen. Damit bliebe nur die Fragen der Endianness / Endigkeit / Bytereihefolge zu klären. Die Bytes erhält man via variante Records oder per absolute.

Der schöne Günther 5. Dez 2013 11:38

AW: Float Zahlen in Hex Zahlen umwandeln
 
Stimmt, das
Delphi-Quellcode:
absolute
-Keyword wär auch noch eine Möglichkeit. Hier aber nochmal mit einem Byte-Pointer der über die Single-Variable wandert, ist ja im Endeffekt das gleiche. Und macht mir persönlich weniger Angst.

Und ja, Big- oder Little-Endian müsste auch noch geklärt werden...

Delphi-Quellcode:
procedure TForm5.FormCreate(Sender: TObject);
var
   float: Single;
   byteNo: Integer;

   bytePtr: PByte;

   numHexDigits: Integer;
begin

   float := System.Pi();
   numHexDigits := 16 div (Byte.Size()*8);

   self.Caption := float.ToString()+'=';
   for byteNo := 0 to Pred(float.Size()) do
      self.Caption := self.Caption + float.Bytes[byteNo].ToHexString(numHexDigits);


   memo1.Lines.Append(float.ToString()+' entspricht...');
   bytePtr := Addr(float);
   for byteNo := 0 to Pred(float.Size()) do begin
      memo1.Lines.Append(bytePtr^.ToString() + ' = 0x'+bytePtr^.ToHexString(numHexDigits));
      Inc(bytePtr);
   end;


end;

gammatester 5. Dez 2013 11:50

AW: Float Zahlen in Hex Zahlen umwandeln
 
Mit Delphi 7 wird das so nicht gehen. Sicher und ohne Angst kann man es so machen (mit write als Ersatz für Sende_Hex):
Delphi-Quellcode:
type
  TSingleByteArray = packed array[0..3] of byte; {Single as array of bytes}
var
  s: single;
  i: integer;
begin
  s := 1.12;
  for i:=0 to 3 do write(TSingleByteArray(s)[i]:4);
end;

danielA 5. Dez 2013 11:56

AW: Float Zahlen in Hex Zahlen umwandeln
 
Probier mal folgendes:

Code:

...

type
  TConvert32Bit = (Conv_AsFloat, Conv_AsInteger, Conv_AsByte, Conv_AsChar, Conv_AsSingle);

  TConvertRecord = record
  case TConvert32Bit of
       Conv_AsFloat  : (FloatValue : Double);
       Conv_AsInteger : (IntValue : Integer);
       Conv_AsByte   : (ByteHH, ByteHL, ByteLH, ByteLL : Byte);
       Conv_AsChar   : (CharHH, CharHL, CharLH, CharLL : Char);
       Conv_AsSingle : (HighSingle, LowSingle : Single);
  end;


  TForm1 = class(TForm)


...


implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var ConvertVar : TConvertRecord;
    FloatValue : Real;
begin
  FloatValue := 0.0;
  ConvertVar.FloatValue := FloatValue;
  ShowMessage(IntToHex(ConvertVar.IntValue, 8));

  FloatValue := 1234.1234;
  ConvertVar.FloatValue := FloatValue;
  ShowMessage(IntToHex(ConvertVar.IntValue, 8));
end;

p80286 5. Dez 2013 12:19

AW: Float Zahlen in Hex Zahlen umwandeln
 
Noch'n Vorschlag:
Delphi-Quellcode:
var
  i : integer;
  a : single;
  b : double;
  pa : pbytearray;
  dummy : string;
begin
  dummy:='';
  a:=1/3+4;
  b:=a;

  memo1.Lines.Add(format('%-3.6g',[a]));
  memo1.Lines.Add(format('%-3.6g',[a]));

  dummy:='';
  pa:=@a;
  for i:=0 to sizeof(a)-1 do
    dummy:=dummy+inttohex(pa^[i],2)+' ';
  memo1.Lines.Add(dummy);

  dummy:='';
  pa:=@b;
  for i:=0 to sizeof(b)-1 do
    dummy:=dummy+inttohex(pa^[i],2)+' ';
  memo1.Lines.Add(dummy);

end;
Gruß
K-H

gammatester 5. Dez 2013 12:22

AW: Float Zahlen in Hex Zahlen umwandeln
 
Zitat:

Zitat von danielA (Beitrag 1238613)
Probier mal folgendes:

Code:

...

type
  TConvert32Bit = (Conv_AsFloat, Conv_AsInteger, Conv_AsByte, Conv_AsChar, Conv_AsSingle);

  TConvertRecord = record
  case TConvert32Bit of
       Conv_AsFloat  : (FloatValue : Double);
...

Damit kann man kein Single konvertieren. Es kommt zwar was raus, aber es ist völliger Schrott.

danielA 5. Dez 2013 13:04

AW: Float Zahlen in Hex Zahlen umwandeln
 
@Gammatester

Dein Arroganter Kommentar zeigt mir, dass du das Prinzip welches ich hier zeigen wollte definitiv nicht begriffen hast bzw. nicht kennst!
Sonst hättest du mich sicher auf den Fehler hinweisen können!
Im übrigen kosten Typecasts ne Menge Zeit und sind bei so einer einfachen umwandlung schlichtweg überflüssig!

@An den Rest
ich habe mich leider beim Byteszählen vertan. Hier nun noch einmal die berichtigte Variante

Code:


...

type
  TConvert32Bit = (Conv_AsFloat, Conv_AsInteger, Conv_AsByte, Conv_AsChar, Conv_AsCardinal);

  TConvertRecord = record
  case TConvert32Bit of
       Conv_AsFloat : (FloatValue : Single);
       Conv_AsInteger : (IntValue : Integer);
       Conv_AsByte  : (ByteHH, ByteHL, ByteLH, ByteLL : Byte);
       Conv_AsChar  : (CharHH, CharHL, CharLH, CharLL : Char);
       Conv_AsCardinal : (CardinalValue : Cardinal);
  end;


  TForm1 = class(TForm)


...


implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var ConvertVar : TConvertRecord;
    FloatValue : Single;
begin
  FloatValue := 0.0;
  ConvertVar.FloatValue := FloatValue;
  ShowMessage(IntToHex(ConvertVar.IntValue, 8));

  FloatValue := 1234.1234;
  ConvertVar.FloatValue := FloatValue;
  ShowMessage(IntToHex(ConvertVar.IntValue, 8));
end;
PS.: der Ton spielt die Musik. Ich habe kein Problem damit, wenn man mich auf Fehler hinweist. Die Frage ist nur Wie!

gammatester 5. Dez 2013 13:52

AW: Float Zahlen in Hex Zahlen umwandeln
 
Zitat:

Zitat von danielA (Beitrag 1238630)
@Gammatester
Dein Arroganter Kommentar zeigt mir, dass du das Prinzip welches ich hier zeigen wollte definitiv nicht begriffen hast bzw. nicht kennst!
Sonst hättest du mich sicher auf den Fehler hinweisen können!
Im übrigen kosten Typecasts ne Menge Zeit und sind bei so einer einfachen umwandlung schlichtweg überflüssig!

Der Ausdruck 'Schrott' bezog sich auf das Ergebnis nicht auf Deinen Code (das der fehlerhaft war, ist ja unzweifelhaft). Im Übrigen brauchen Typecasts nicht nur nicht 'ne Menge Zeit' sondern sondern gar keine, weil die Variable vom Compiler re-interpretiert wird, und mM ist das auch einfacher und durchsichtiger als Deine Konstruktion, die einen impliziten verdeckten Typecast gleichkommt.

himitsu 5. Dez 2013 14:03

AW: Float Zahlen in Hex Zahlen umwandeln
 
Zitat:

Zitat von Darlo (Beitrag 1238605)
Hi,

kann ja sein, dass ich jetzt komplett daneben liege, aber meines Wissens sind Hex-Zahlen nur Integer.....

Sollte ich hier richtig liegen dann macht es Sinn, dass es
Delphi-Quellcode:
IntToHex()
gibt aber kein
Delphi-Quellcode:
FloatToHex()
;-)

HEX ist kein Integer.

Eine Hexadezimalzahl ist eine "Zahl" in Hexadezimaler Darstellung. (0-15 pro Ziffer)

Einen Integer kann mal man auch in vielen Zahlensystemen darstellen (meisten kennen wir aber das Dezimalsystem mit 0-9 pro Ziffer)
oder Binär mit 0-1 pro Ziffer.

Als ganze Zahl läßt sich aber das Zahlensystem leicht umrechnen, weswegen es auch eine passende Funktion gibt.

Wenn man aber den "binären" Speicherhinhalt des "Float" betrachtet, dann ist der auch Hexadezimal darstellbar, aber der enthaltene Fießkommawert ist es nicht, weswegen es auch keine funktion dafür gibt.
Für den binären Inhalt des speichers gibt es z.B. Delphi-Referenz durchsuchenBinToHex.

Aber wie schon erwähnt wurde, muß man da wissen in welcher Reihenfolge die Bytes übertragen werden müssen.

IntToHex stellt die Bytes z.B. in einer anderen Reihenfolge dar, wie das BinToHex.
BinToHex: kleines Byte im speicher = links und kleines Byte im Hex-String ist auch links
IntToHex: großes Byte im Hex ist links (also kleines Byte ist rechts)

p80286 5. Dez 2013 15:12

AW: Float Zahlen in Hex Zahlen umwandeln
 
Zitat:

Zitat von himitsu (Beitrag 1238642)
Aber wie schon erwähnt wurde, muß man da wissen in welcher Reihenfolge die Bytes übertragen werden müssen.

IntToHex stellt die Bytes z.B. in einer anderen Reihenfolge dar, wie das BinToHex.

BinToHex: kleines Byte im speicher = links und kleines Byte im Hex-String ist auch links
IntToHex: großes Byte im Hex ist links (also kleines Byte ist rechts)

Schön, daß das mal jemand ausformuliert, in der Hilfe wird das nicht explizit erwähnt.
(Und welcher Anfänger und wieviele Fortgeschrittene haben noch nie etwas von LittleEndian und BigEndian gehört?)

Gruß
K-H

danielA 5. Dez 2013 16:37

AW: Float Zahlen in Hex Zahlen umwandeln
 
@gammatester

Nun ja, da werden sich die Geister wohl ewig scheiden und das ist ja auch nicht schlimm ;-).

Typecast:
tatsächlich ist es so, dass ich bereits aus Programmen Typecasts herausgenommen habe, indem ich einmal den Typ bestimmt und anschließend einer Variable zugewiesen habe. Dadurch habe ich Sekunden(!) gewonnen. So ganz ohne Rechenaufwand kann das also nicht stattfinden. Diskutieren kann man allerdings darüber, ob ein Cast auf ein "array of byte" verglichen mit einem Cast auf eine Klasse tatsächlich vergleichbar sind.

Ob mein "Konstrukt" weniger durchsichtig ist, kann ich nicht beurteilen.

Einfacher, performanter und flexibler ist es auf jeden Fall, denn:

Das Record nimmt genau 4 Byte im Speicher ein. Nicht mehr und nicht weniger. Durch Definition des Records gibt es keine Typumwandlung im eigentlichen Sinne. Im Grunde teilen sich 11 Variablen verschiedenen Typs den selben Speicherbereich. Nämlich genau die vom Record belegten 4 byte.

FloatValue, IntValue und CardinalValue dabei die kompletten 4 byte. Die Variablen ByteHH, ByteHL, ByteLH, ByteLL von links nach rechts ebenfalls. Das selbe gilt für die Variante mit den 4 Charactern. (H steht für High, L für Low)

Für die Umwandlung von Single in Integer sind demnach genau(!) ein Schreib + Ein Lesezyklus notwendig.

Belibige Bytekonvertierungen sind ebenfalls problemlos ohne Aufwand möglich. Ich weiß nicht was du mehr willst?

p80286 5. Dez 2013 17:35

AW: Float Zahlen in Hex Zahlen umwandeln
 
Aber Hallo,
gibt's jetzt wieder Glaubenskriege?
Meiner Unmaßgeblichen Meinung nach ist es egal ob ich mit einem varianten Record oder mehreren Typen arbeite. Solange ich die Daten nicht extra noch einmal schreiben muß, was bei 4 Byte ja nun auch nicht soo viel ist, ist es eigentlich nur Geschmackssache. Wobei ich zugeben muß, daß variante Records sich u.U. nicht so einfach erschließen.
(übrigens
Delphi-Quellcode:
absolute
ist irgendwie untergegangen!?)
Was ich bezweifle, ist, daß Typecasts Zeit kosten, da es sich ja eigentlich um eine andere Interpretation vorhandener Daten handelt. Wäre schon schön, wenn das jemand mit einem Beispiel belegen könnte.

Gruß
K-H

himitsu 5. Dez 2013 17:54

AW: Float Zahlen in Hex Zahlen umwandeln
 
Zitat:

Zitat von p80286 (Beitrag 1238680)
Was ich bezweifle, ist, daß Typecasts Zeit kosten, da es sich ja eigentlich um eine andere Interpretation vorhandener Daten handelt.

Jupp.


Mit ein paar Ausnahmen.
- implizite/explizite "TypCasts" über Record-Operatoren
- gewisse TypCast von z.B. Strings, wo Delphi ein bissl CompilerMagic drin versteckt und z.B. Konvertierungen der String und/oder CodePages vornimmt

Mikkey 5. Dez 2013 18:06

AW: Float Zahlen in Hex Zahlen umwandeln
 
Zitat:

Zitat von danielA (Beitrag 1238671)
Typecast:
tatsächlich ist es so, dass ich bereits aus Programmen Typecasts herausgenommen habe, indem ich einmal den Typ bestimmt und anschließend einer Variable zugewiesen habe. Dadurch habe ich Sekunden(!) gewonnen. So ganz ohne Rechenaufwand kann das also nicht stattfinden. Diskutieren kann man allerdings darüber, ob ein Cast auf ein "array of byte" verglichen mit einem Cast auf eine Klasse tatsächlich vergleichbar sind.

Typecasts auf eine Klasse müssen mehr Rechenaufwand bedeuten, da sonst beim Cast einer unpassenden Referenz keine Ausnahme geworfen werden könnte. Irgendwo muss also eine Überprüfung stattfinden, ob die Referenz, die gecastet werden soll auch zu dem Zieltyp passt.

Bei Casts auf einen nicht-Klassen-Typ erfolgt keine Überprüfung.

Allerdings entspricht die Record-Methode weit eher der Typsicherheit, die ich an der Uni mal mit dem Ur-Pascal aufgenommen habe ;-)

himitsu 5. Dez 2013 18:17

AW: Float Zahlen in Hex Zahlen umwandeln
 
Records mit varianten Teilen entspricht quasi dem Absolute.
Nur daß beim Absolute keinerlei Prüfungen vom Compiler vorgenommen werden. (beim Record werden gemanagete Typen "verboten")

Ob man nun den Record nimmer und die Daten erst reinkopiert, um sie dann "gecastet" da auszulesen oder ob man den Typ direkt zum Casten nimmt, ist geschmackssache, wobei der direkte Weg sich die zusätzliche Kopieroperation erspart.

Man kann sich auch gern eine generische Funktion schreiben, welche die eine Variable als Parameter annimmt und das im anderen Format ausgibt.
Entspricht dann einem "expliziten" Cast, welchen man sich via Record-Operatoren basteln kann.

Und dann gibt es noch den Weg über einen Record-Helper, wo man sich eine Konvertierungsfunktion basteln kann, wie z.B. das .ToString an Klassen und neuerdings auch an einigen generischen Typen wie z.B. den Integern.


Oder man geht den klassischen Weg und nutzt eine Konvertierungsprozedur mit In-Param und Out/Var-Param, oder das Out als Result.

danielA 5. Dez 2013 19:06

AW: Float Zahlen in Hex Zahlen umwandeln
 
Hättest du vielleicht mal ein Beispiel oder einen Link zu der Absolute Methode?
Diese direktive kenne ich überhaupt nicht und wird in der Delphi- Hilfe von XE2 auch nur in einer Tabelle als direktive erwähnt aber mit keinem Wort erklärt.
Eine Möglichkeit gäbe es zur eigentlichen Aufgabe aber nocht. Aus Faulheit hätte ich diese sicher auch gewählt ;-)

Code:

var SingleVar : Single;
    Intvar : integer;
begin
  SingleVar := 1.1234;
  move(SingleVar, IntVar, 4);
  showmessage(IntToHex(IntVar));
end;

himitsu 5. Dez 2013 20:27

AW: Float Zahlen in Hex Zahlen umwandeln
 
Delphi-Quellcode:
var
  SingleVar: Single;
  IntVar: Integer absolute SingleVar;
begin
  SingleVar := 1.1234;
  ShowMessage(IntToHex(IntVar));
end;
Es besagt einfach nur, daß diese Variable an der selben "absoluten" Adresse beginnen soll, wie die angegebene andere Variable.

Aber ein Cast ist da eh besser/einfacher, vorallem da der Compiler einem bescheid gibt, wenn der Cast nicht "möglich" ist, z.B. aufgrund der Typen oder Speichergröße.
Delphi-Quellcode:
var
  SingleVar: Single;
begin
  SingleVar := 1.1234;
  ShowMessage(IntToHex(Integer(SingleVar)));
end;

danielA 6. Dez 2013 09:07

AW: Float Zahlen in Hex Zahlen umwandeln
 
Hallo Himitsu,

vielen Dank für das Beispiel.

Die Sache mit Absolute scheint wirklich sehr interessant zu sein. Das werde ich mir merken.

Beim zweiten Beispiel...
Nun ja ich finde es trotzdem Merkwürdig, dass der Compiler da meckert. Belegen doch beide Werte gleich viel Speicher. Vermutlich konnte man sich nicht einigen ob man bei diesem Cast nur den Ganzzahligen Wert oder den binär betrachteten Wert des belegten Speichers zurückgibt.
Eine Möglichkeit diesen Cast trotzdem auszuführen währe dann aber noch folgende:

Code:

var
  SingleVar: Single;
begin
  SingleVar := 1.1234;
  ShowMessage(IntToHex(Integer(Pointer(SingleVar)),8));
end;
Dabei geht aber leider wieder die Typüberprüfung verloren. Da SingleVar von jedem Typ sein könnte.
Mir persönlich gefällt dann Deine Variante mit Absolute doch besser, wenn keine Bytevertauschungen (Big <-> Little Endian) durgeführt werden müssen.

himitsu 6. Dez 2013 10:08

AW: Float Zahlen in Hex Zahlen umwandeln
 
Es kann sein, daß der Compiler dort eine Typprüfung in der Konvertierung vornimmt. Macht die Compilermagic bei einigen Typen.
Wie z.B. auch zwischen ANSI- und UnicodeStrings, wobei dort nur eine Warnung angezeigt wird, daß man da auspassen sollte.

Man kann auch ganz "böse" sein und sämtliche Prüfungen umgegehn.
Delphi-Quellcode:
var
  SingleVar: Single;
begin
  SingleVar := 1.1234;
  ShowMessage(IntToHex(PInteger(@SingleVar)^, 8));
end;
Aber genauso, wie beim Absolute, sollte man beim wilden Rumgepointere unbedingt aufpassen, was man macht und möglichst auch verstehn warum man es so macht.

PS: [DELPHI]...[/DELPHI]

p80286 6. Dez 2013 10:45

AW: Float Zahlen in Hex Zahlen umwandeln
 
Zitat:

Zitat von danielA (Beitrag 1238731)
Mir persönlich gefällt dann Deine Variante mit Absolute doch besser, wenn keine Bytevertauschungen (Big <-> Little Endian) durgeführt werden müssen.

Vorsicht! bei Variablendeklarationen mit Absolute hast Du zwei Variablen, die den gleichen Inhalt haben, wenn Du das "unterwegs" vergisst, kannst Du durchaus ungewollte Effekte erreichen.
Und im Übrigen gilt natürlich
Zitat:

Aber genauso, wie beim Absolute, sollte man beim wilden Rumgepointere unbedingt aufpassen, was man macht und möglichst auch verstehn warum man es so macht.
Gruß
K-H

danielA 6. Dez 2013 11:49

AW: Float Zahlen in Hex Zahlen umwandeln
 
Zitat:

Vorsicht! bei Variablendeklarationen mit Absolute hast Du zwei Variablen, die den gleichen Inhalt haben, wenn Du das "unterwegs" vergisst, kannst Du durchaus ungewollte Effekte erreichen.
Ne ne dass beide Variablen den selben Speicher referenzieren und das nur benutzt werden sollte, wenn man weiß was man tut ist schon klar.

Ja und das Thema Strings ist ja mittlerweile wirklich zu einer Wissenschaft für sich geworden. Ich selbst bin gerade am Umstieg von Delphi6 auf die XE2 dabei und habe noch einige 100000 Zeilen Quellcode zu konvertieren. Im allgemeinen macht Delphi das ja alles von alleine aber gerade Low Level programmierte Sachen, in denen mit String bzw. PChar gearbeitet wurde, ist doch einiges an eingriffen notwendig.

Wenn ich das richtig verstanden habe ist der Typ AnsiString in erster Linie für SingleByte Zeichensätze gedacht. Unterstützt aber auch Multibyte, während UnicodeStrings von Vorneherein als Multibytezeichensatz angenommen werden kann. Wobei UnicodeStrings auch AnsiStrings enthalten können. Eine Warnung scheint mir deshalb doch auch ziemlich Sinnvoll.

Aber ich glaube ich werde jetzt Off Topic ...


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:46 Uhr.

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