Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi IEEE-Float to Real (https://www.delphipraxis.net/9898-ieee-float-real.html)

Sanchez 7. Okt 2003 12:53


IEEE-Float to Real
 
Hallo erstmal,
Ich bekomme eine IEEE-Float-Zahl binär vom Siemens Simatic S7 (glaube ich halt, falls das nicht stimmt, bitte sagen).

z.B.

Code:
1  = 11111100000000010000000000000000
2  = 00000010000000000000000000000000
5  = 00000010000001010000000000000000
-5 = 00000011000001010000000000000000
Jetzt möchte ich daraus eine Delphi-Gleitkommazahl machen hat jemand eine Idee wie das geht???

Mit dieser Formel sollte es doch normalerweise funktionieren, oder?

(-1)s x 2e-127 x (1.m)

Hab ich eventuell die 32 bit falsch aufgeteilt?
Mein erster gedanke:
1 11111000 00000010000000000000000
s e m

Das Vorzeichen (s) sollte doch bei 1 nicht negativ sein. Helft mir bitte

grüße, daniel

Sanchez 7. Okt 2003 14:09

Re: IEEE-Float to Real
 
eventuell bin ich einen Schritt weiter. Ich nehme an, dass die einzelnen Bits umgedreht werden müssen, bei 1 und -1 stimmts dann schon mal. Ansonsten bin ich zu weit von Soll-Ergebnis weg:

Code:
5  = 00000010 00000101 00000000 00000000 //so kommts rein
     01000000 10100000 00000000 00000000 //umgedreht
Vorzeichen = 0
Exponent  = 10000001
Mantisse  = 01000000000000000000000
Kommt aber was um 4.83... raus, so ungenau kanns doch nicht sein, oder doch.

Was mache ich falsch?

Delphianer 7. Okt 2003 14:29

Re: IEEE-Float to Real
 
Hallo,

das 8-Bitweise Rumdrehen ist schon richtig, wenn ich mich jetzt nicht vertan habe, kommen genau die richtigen Ergebnisse heraus.

Viele Grüße

Sanchez 7. Okt 2003 14:39

Re: IEEE-Float to Real
 
nein, es kommt eben nicht das richtige raus (oder ich rechne die ganze Zeit falsch)

Nochmals das Beispiel von vorher:

Code:
bei der Sps gebe ich 5 ein
    00000010 00000101 00000000 00000000 //das Empfange ich mit meiner Software
     01000000 10100000 00000000 00000000 //umgedreht
Vorzeichen = 0 
Exponent  = 10000001 
Mantisse  = 01000000000000000000000 

Ergibt jetz für die Formel:
(-1)^0 x 2^(129-127) x (1.2097152) = 4.83.....

Ich habe aber 5 eingegeben, also liegt irgendwo noch ein Fehler in meinem Ansatz
:wall:

Delphianer 7. Okt 2003 14:45

Re: IEEE-Float to Real
 
Ok, versuche ich es nochmal:

Vorzeichen = 0
Exponent = 10000001
Mantisse = 01000000000000000000000

(-1)^0 x 2^(129-127) x (1.01B) = 100B * 1.01B = 101B = 5D

Wennschon, mußt Du alles binär rechnen.

Viele Grüße

Sanchez 7. Okt 2003 15:06

Re: IEEE-Float to Real
 
Es scheint tatsächlich zu funktionieren.
Jetzt fehlt mir nur noch der Code. Der dürfte jetzt allerdings jetzt das kleinere Problem sein.


:firejump:

Domino 7. Okt 2003 21:40

Re: IEEE-Float to Real
 
Hatte das gleiche Problem.
Wichtig hierbei ist zu beachten, dass die S7-Steuerung die Bytes in umgekehrter Reihenfolge ausgibt. Um daraus eine single-Zahl zu erhalten, musst Du die Reihenfolge der 4 Bytes umdrehen!

Hier ein Auszug zum Umwandeln von 4 eingelesenen Bytes in eine single-Variable.

var
buffer : array[0..3] of byte; //Hierin sind die 4 Byte einzulesen
abData : array[0..3] of byte;
rData : single;
begin
// Routine zum Einlesen der 4 Byte von der S7-Steuerung in buffer ...
// beispielsweise mit der Funktion d_field_read ...
//

(************************************************* ******************)
(* Die S7-Steuerung gibt die Bytes in umgekehrter Reihenfolge aus! *)
(************************************************* ******************)

// zunächst Reihenfolge der 4 Byte vertauschen
for i := 0 to 3 do
abData[i] := buffer[3-i];

//Umwandeln der 4 Byte in in single-Variable
CopyMemory(@rData, @abData, 4); //Windows-Funktion, siehe Hilfe Windows SDK

//das wars ..
end;

Sanchez 8. Okt 2003 06:42

Re: IEEE-Float to Real
 
@Domino:
Bist du dir sicher, dass die Bytes in falscher Reihenfolge ausgegeben werden?
Für mich sieht es eher so aus, als wären die einzelnen Bytes verdreht, aber durchaus in der richtigen Reihenfolge.

Hier z.B.

Code:
5  = 00000010 00000101 00000000 00000000 //so kommts rein
     01000000 10100000 00000000 00000000 //umgedreht

Wenn ich die Bytes umdrehe
     00000000 00000000 00000101 00000010
hab ich

Vorzeichen 0
Exponent  00000000
Mantisse  0000000 100000101 00000010

Gibt doch einen ziemlich kleinen Wert, aber nicht 5.
Eventuell ist es auch möglich, dass das umdrehen der Bytereihenfolge schon mein OCX macht.
Bei dem Control ist es so, dass ich die Werte bereits in Binär-String geliefert bekomme, das machts es wenn ich es so mache am einfachsten denke ich.

Aber den Ansatz der Umwandlung hast du auch gleich wie ich?

Domino 8. Okt 2003 21:06

Re: IEEE-Float to Real
 
Hallo,
ich kenne dein OCX nicht, mit dem du die Daten von der S7-Steuerung holst. Die Reihenfolge der Bits ist jedenfalls umgedreht. Probier doch mal, nachdem du die Bits der 4 Bytes vertauscht hast, folgenden Code:

procedure myProc;
var
buffer : array[0..3] of byte;
abData : array[0..3] of byte;
rData : single;
i : integer;
begin
//Beispiel für die Zahl 5:
// buffer enthält die 4 umgedrehten Bytes:
buffer[0] := 64; // binär 01000000
buffer[1] := 160; // binär 10100000
buffer[2] := 0; // binär 00000000
buffer[3] := 0; // binär 00000000

// Reihenfolge der 4 Byte vertauschen
for i := 0 to 3 do
abData[i] := buffer[3-i];

//Umwandeln der 4 Byte in in single-Variable
CopyMemory(@rData, @abData, 4); //Windows-Funktion, siehe Hilfe Windows SDK
// als Ergebnis enthält rData die Zahl 5 !!

//Beispiel für die Zahl 4:
// buffer enthält die 4 umgedrehten Bytes:
buffer[0] := 64; // binär 01000000
buffer[1] := 128; // binär 10100000
buffer[2] := 0; // binär 00000000
buffer[3] := 0; // binär 00000000

// Reihenfolge der 4 Byte vertauschen
for i := 0 to 3 do
abData[i] := buffer[3-i];

//Umwandeln der 4 Byte in in single-Variable
CopyMemory(@rData, @abData, 4);
// als Ergebnis enthält rData die Zahl 4 !!


//Beispiel für 5.01:
// buffer enthält die 4 umgedrehten Bytes:
buffer[0] := 64;
buffer[1] := 160;
buffer[2] := 81;
buffer[3] := 236;

// Reihenfolge der 4 Byte vertauschen
for i := 0 to 3 do
abData[i] := buffer[3-i];

//Umwandeln der 4 Byte in in single-Variable
CopyMemory(@rData, @abData, 4); //Windows-Funktion, siehe Hilfe Windows SDK
// Ergebnis für rData : 5.01000022888184 (single-Genaugkeit !)


//Beispiel für 5.02:
// buffer enthält die 4 umgedrehten Bytes:
buffer[0] := 64;
buffer[1] := 160;
buffer[2] := 163;
buffer[3] := 215;

// Reihenfolge der 4 Byte vertauschen
for i := 0 to 3 do
abData[i] := buffer[3-i];

//Umwandeln der 4 Byte in in single-Variable
CopyMemory(@rData, @abData, 4); //Windows-Funktion, siehe Hilfe Windows SDK
// Ergebnis für rData : 5.01999998092651 (single-Genaugkeit !)


end;

PS: Welches OCX benutzt du?


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:55 Uhr.

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