TIA Umwandlung negativer Wert von LINT auf LREAL

Das ist doch bekloppt.
"IEEE" bedeutet nicht REAL. "IEEE 754" wurde REAL bedeuten. Aber auch das wäre zu diskret. Warum nicht einfach "REAL" schreiben ?
Ich hätte auch nicht kapiert dass die Daten in die Kolonne mit "IEEE" REALs sind.
Und auf den Grund hat ModbusDani1995 eine nicht fungierende Anlage in 3 Jahren gehabt.
 
Das ist doch bekloppt.
"IEEE" bedeutet nicht REAL. "IEEE 754" wurde REAL bedeuten. Aber auch das wäre zu diskret. Warum nicht einfach "REAL" schreiben ?
Ich hätte auch nicht kapiert dass die Daten in die Kolonne mit "IEEE" REALs sind.
Und auf den Grund hat ModbusDani1995 eine nicht fungierende Anlage in 3 Jahren gehabt.
und von Algodue bekommt man weder Antwort noch Support.

Bei unseren anderen Modbus Geräten funktionierte alles sehr schnell (Sick, Flexim, ... )
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Aber es gibt in der S7 sicher elegantere Wege wie man das machen kann, gibt denke ich sogar Befehle für wandeln nach Zweierkomplement.
In S7 gibt es in AWL Befehle für das Umkehren des Vorzeichens: NEGI für INT (16 Bit) und NEGD für DINT (32 Bit).
Für LINT (64 Bit) ist mir in AWL bisher noch nichts untergekommen (und ich werde es auch nicht vermissen).

Übrigens:
die Befehle NEGI und NEGD wandeln nicht "nach Zweierkomplement", sondern negieren (invertieren) das Vorzeichen einer Variablen, die definitionsgemäss die ZweierkomplementDarstellung benutzt (SINT, INT, DINT, LINT, ...).

Gibt es auch Befehle für die (RückUm-)Wandlung einer negativen Zahl in ZweierKomplementDarstellung in eine positive Zahl?
Klares "jain". Gibt es: NEGI und NEGD, die ja beide das Vorzeichen einer Zahl in ZweierKomplementDarstellung wechseln. Eigene Befehle für die RückUmwandlung gibt es natürlich nicht.

Man könnte jetzt manuell das Vorzeichenbit aus-maskieren, wandeln und dann irgendwo mal -1 rechnen... Siehe Screenshot.
Wie bereits erwähnt, kann man in SCL, ST, FUP, KOP ohne spezielle Befehle das Vorzeichen durch Multiplikation ( X := X * -1 ; ) mit -1 umkehren.

Wie noch nicht erwähnt, kann man in SCL, ST, FUP, KOP ohne spezielle Befehle das Vorzeichen durch Subtraktion ( X := 0 - X ; ) einer Zahl von 0 umkehren. (Eine Subtraktion sollte theoretisch schneller sein als eine Multiplikation)

Wie ebenfalls noch nicht erwähnt, geht es aber auch noch einfacher ohne Multiplikation und ohne Subtraktion, da man "direkt" negieren kann:
X := -X ;
 
Zuletzt bearbeitet:
Wie noch nicht erwähnt, kann man (...) das Vorzeichen durch Subtraktion ( X := 0 - X ; ) einer Zahl von 0 umkehren.
Ach ja, diese Möglichkeit hatte ich noch vergessen. (y) Damit kann man die Umrechnung auf eine reine Subtraktion/Addition umformen und umstellen und zusammenfassen, so dass die Umwandlung von "nur negatives Vorzeichen" zu Zweierkomplement in #13 auf die simple Subtraktion reduziert werden kann: #INT31_DINT := 16#80000000 - #diTemp;
 
Was für ein Slice-Zugriff sollte da sinnvoll sein?
Beispiele Darstellung Vorzeichen + Betrag muss zu Zweierkomplement geändert werden:
Code:
10000000_00000000_00000000_00001111  (-)15 Vorzeichen + Betrag
11111111_11111111_11111111_11110001  -15 im Zweierkomplement

10000000_00110011_01110111_11111111  (-)3373055 Vorzeichen + Betrag
11111111_11001100_10001000_00000001  -3373055 im Zweierkomplement
 
Zuviel Werbung?
-> Hier kostenlos registrieren
war doof, habe ich gerade selbst gemerkt :D. Hatte die doofe Frage aber zumindest angekündigt :).
War irgendwie nur auf den Trichter mit das Vorzeichenbit zu drehen
 
Zuletzt bearbeitet:
Was für ein Slice-Zugriff sollte da sinnvoll sein?
Ich vermute, dass es um das Isolieren des höchstwertigen Bits geht.
Einerseits, um es abzufragen, ob eine negative Zahl vorliegt. *)
Andererseits, um es plattzumachen, damit man den Betrag erhält, den man dann in eine negative Zahl wandeln kann.

*) Für diesen Zweck müsste man gar nicht das "VorzeichenBit" isolieren. Man könnte einfach abfragen, ob die Zahl <0 ist.
 
A3Q hatte die Aufgabenstellung missverstanden und meinte, die Aufgabe müsse das Vorzeichenbit umdrehen. Es geht aber darum, das Vorzeichenbit zu behalten und bei negativen Werten den Betrag in die Zweierkomplementdarstellung umzuwandeln. Das kann man mit verschiedenen Algorithmen erreichen:
Code:
(1) #INT31_DINT := -(#diTemp AND 16#7FFFFFFF); // VZ auf 0 durch ausblenden, dann negieren -X  (*!)

(2) #INT31_DINT := -(#diTemp + 16#80000000);   // VZ auf 0 umdrehen, dann negieren -X  (*!)

(3) #INT31_DINT := -(#diTemp - 16#80000000);   // VZ auf 0 umdrehen, dann negieren -X  (*!)

(4) #INT31_DINT := 16#80000000 - #diTemp;      // VZ auf 0 umdrehen und negieren durch 0-X  (**)
siehe die fertige Function INT31_DINT (Int31 zu DInt) in Beitrag #13

(*!) Sonderfall 16#80000000
Die Datenquelle verwendet möglicherweise den Wert 16#80000000 entsprechend "-0" ? In der Zweierkomplementdarstellung bedeutet 16#80000000 = -2.147.483.648, da würde das Negieren -X oder *-1 zu einem falschen Ergebnis führen und 16#80000000 müsste gesondert behandelt werden.
(**) Die Formel (4) hat das Problem nicht, da wird 16#80000000 = "-0" korrekt zu 0 umgewandelt. :)

PS: kann man auch eine Formel finden, die ohne bedingte Sprünge (Fallunterscheidung, IF...THEN) auskommt?

PPS: in den Formeln (1)(2)(3) das Negieren nicht mit -X machen, sondern mit 0-X oder *-1 machen, dann wandeln die auch 16#80000000 = "-0" korrekt zu 0
Code:
(1) #INT31_DINT := 0 - (#diTemp AND 16#7FFFFFFF); // VZ auf 0 durch ausblenden, dann negieren 0-X
(2) #INT31_DINT := 0 - (#diTemp + 16#80000000);   // VZ auf 0 umdrehen, dann negieren 0-X
(3) #INT31_DINT := 0 - (#diTemp - 16#80000000);   // VZ auf 0 umdrehen, dann negieren 0-X
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Es geht aber darum, das Vorzeichenbit zu behalten und bei negativen Werten den Betrag in die Zweierkomplementdarstellung umzuwandeln.
Das höchstwertige Bit ("VorzeichenBit") muss man nicht "beibehalten", es wird in der ZweierKomplementDarstellung beim VorzeichenWechsel neu gebildet.

PS: kann man auch eine Formel finden, die ohne bedingte Sprünge (Fallunterscheidung, IF...THEN) auskommt?
Kann man. Zwar mit FallUnterscheidung aber unter Verzicht auf IF...THEN. Sieht aber recht unelegant aus.
Habe es der Einfachheit und (eines Restes von) Übersichtlichkeit wegen mal als 3-Zeiler geschrieben:
Code:
Betrag := DWORD_TO_DINT ( DINT_TO_DWORD ( VZmitBetrag ) AND 16#7FFFFFFF ) ;  // ggfs   Betrag := VZmitBetrag AND 16#7FFFFFFF ;

VZfaktor := BOOL_TO_DINT ( VZmitBetrag < 0 ) * DINT ( -1 ) + BOOL_TO_DINT ( VZmitBetrag > 0 ) * DINT ( 1 ) ;

ZweierKomplementDarstellung := VZfaktor * Betrag ;

// 'VZfaktor' liefert den Wert 1, wenn >0 und -1, wenn <0, sonst 0. Vergleichbar mit der Funktion SIGN() in manchen ProgrammierSprachen.
// 'Betrag' ist identisch mit der positiven Zahl in der ZweierKomplementDarstellung.
// Als 'VZmitBetrag' wird hier die Darstellung als NICHT-Zweierkomplement bezeichnet, also die umzuwandelnde EingangsGrösse.
// Es wird unterstellt, dass alle Operatoren sich gaaanz "normal" verhalten, also so arbeiten, wie sie es in der ZweierKomplement-
// Darstellung nötig ist.

Anmerkung zu VB und TRUE:
- In VB hat TRUE den Wert -1.
- in SCL hat TRUE den Wert 1.
Dieser Unterschied ist zu berücksichtigen, wenn man Ähnliches in VB programmieren möchte.
 
Wie hilfreich es doch ist, wenn man die Aufgabenstellung richtig formuliert. ;)
Zerlegen in Vorzeichen und Betrag und dann vorzeichenabhängig mit 1 oder -1 multiplizieren ist der Weg zum Einzeiler.
Code:
// alle Variablen DINT !
// Insbesondere VZmitBetrag muss DINT, damit der SCL-Compiler das SHR() vorzeichenrichtig einsetzt.

Betrag := VZmitBetrag AND 16#7FFFFFFF;
VZfaktor := SHR(IN:=VZmitBetrag, N:=31) OR 1;
ZweierKomplementDarstellung := VZfaktor * Betrag;

// oder als Einzeiler:
ZweierKomplementDarstellung := (SHR(IN:=VZmitBetrag, N:=31) OR 1) * (VZmitBetrag AND 16#7FFFFFFF);
Und das Gute: es wird auch der Sonderfall 16#80000000 = -0 richtig zu 0 umgewandelt.
Man darf also NICHT die direkte Negation -X verwenden, sondern nur 0-X oder *-1
 
Wie hilfreich es doch ist, wenn man die Aufgabenstellung richtig formuliert. ;)
Und wie hilfreich es wäre, wenn SIEMENS seine Produkte korrekt/zutreffend beschreiben würde.

// Insbesondere VZmitBetrag muss DINT, damit der SCL-Compiler das SHR() vorzeichenrichtig einsetzt.
Tut der Compiler das denn wirklich?

Die Beschreibung des SHR lautet für die DatenTypen BOOL, BYTE, WORD und DWORD
"In dem im Parameter IN vorhandenen Wert werden so viele Bitstellen nach rechts geschoben
und so viele Bitstellen auf der linken Seite durch 0 ersetzt, wie der Inhalt des Parameters N angibt."

Für die DatenTypen INT und DINT gibt es keine Beschreibung ( weil vermutlich nicht zulässig? ).
Und nirgends wird erwähnt, dass der SHR in die Bitstellen, die durch das Schieben frei werden, den Signalzustand des Vorzeichenbits schreibt.

Falls der Compiler also entgegen seiner Beschreibung bei DINT und Rechtsschieben quasi den AWL-SSD statt des AWL-SRD benutzt,
dann ist Deine Schieberei um 31 Bit nach rechts genial: negative Zahlen liefern 16#FFFFFFFF > ( also -1 ) und 0 oder positive Zahlen liefern durch das OR 1 den Wert 16#00000001.

Zerlegen in Vorzeichen und Betrag und dann vorzeichenabhängig mit 1 oder -1 multiplizieren ist der Weg zum Einzeiler.
Genau das war doch mein Ansatz ... na ja, fast ... und hat "nur" zu einem umständlichen DreiZeiler geführt.

Man darf also NICHT die direkte Negation -X verwenden, sondern nur 0-X oder *-1
Stimmt, die "direkte" Negation mittels ZweierKomplementBildung funktioniert - oh Wunder - natürlich nur bei Zahlen in ZweierKomplementDarstellung.
 
Zuletzt bearbeitet:
Zurück
Oben