![]() |
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 |
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:
Oder Mantisse, Exponent usw. einzeln in Hex-Schreibweise übertragen?
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; Was von den Java-ähnlichen Typenhelfern wie (3.14.toString()) in Delphi 7 schon ging weiß ich nicht.
Delphi-Quellcode:
scheint ein paar Helfermethoden für Gleitkommazahlen zu haben...
System.TSingleRec
Oh und Herzlich Willkommen in den Heiligen Hallen des Wissens und des Wahnsinns :hi::corky: |
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:
gibt aber kein
IntToHex()
Delphi-Quellcode:
;-)
FloatToHex()
|
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.
|
AW: Float Zahlen in Hex Zahlen umwandeln
Stimmt, das
Delphi-Quellcode:
-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.
absolute
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; |
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; |
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; |
AW: Float Zahlen in Hex Zahlen umwandeln
Noch'n Vorschlag:
Delphi-Quellcode:
Gruß
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; K-H |
AW: Float Zahlen in Hex Zahlen umwandeln
Zitat:
|
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:
PS.: der Ton spielt die Musik. Ich habe kein Problem damit, wenn man mich auf Fehler hinweist. Die Frage ist nur Wie!... 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; |
AW: Float Zahlen in Hex Zahlen umwandeln
Zitat:
|
AW: Float Zahlen in Hex Zahlen umwandeln
Zitat:
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. ![]() 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) |
AW: Float Zahlen in Hex Zahlen umwandeln
Zitat:
(Und welcher Anfänger und wieviele Fortgeschrittene haben noch nie etwas von LittleEndian und BigEndian gehört?) Gruß K-H |
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? |
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:
ist irgendwie untergegangen!?)
absolute
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 |
AW: Float Zahlen in Hex Zahlen umwandeln
Zitat:
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 |
AW: Float Zahlen in Hex Zahlen umwandeln
Zitat:
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 ;-) |
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. |
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; |
AW: Float Zahlen in Hex Zahlen umwandeln
Delphi-Quellcode:
Es besagt einfach nur, daß diese Variable an der selben "absoluten" Adresse beginnen soll, wie die angegebene andere Variable.
var
SingleVar: Single; IntVar: Integer absolute SingleVar; begin SingleVar := 1.1234; ShowMessage(IntToHex(IntVar)); end; 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; |
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:
Dabei geht aber leider wieder die Typüberprüfung verloren. Da SingleVar von jedem Typ sein könnte.var SingleVar: Single; begin SingleVar := 1.1234; ShowMessage(IntToHex(Integer(Pointer(SingleVar)),8)); end; Mir persönlich gefällt dann Deine Variante mit Absolute doch besser, wenn keine Bytevertauschungen (Big <-> Little Endian) durgeführt werden müssen. |
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:
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.
var
SingleVar: Single; begin SingleVar := 1.1234; ShowMessage(IntToHex(PInteger(@SingleVar)^, 8)); end; PS: [DELPHI]...[/DELPHI] |
AW: Float Zahlen in Hex Zahlen umwandeln
Zitat:
Und im Übrigen gilt natürlich Zitat:
K-H |
AW: Float Zahlen in Hex Zahlen umwandeln
Zitat:
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