TIA TIA16 Warnung bei Berechnung mit Potenz SCL

gochtel

Level-1
Beiträge
100
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo miteinander,
bei folgendem Code, meckert der Compiler die Typconvertierung an. Vorzeichen oder Genauigkeit könnten verloren gehen, sagt es mir.

Code:
#tmp_PV := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / (10 ** #tmp_VISU.DEC_PLACES);

#tmp_VISU.DEC_PLACES ist als INT deklariert.
#tmp_PV als REAL deklariert

Wenn ich es folgendermassen anpasse, meckert der Compiler nur noch den letzten Klammerausdruck an.

Code:
#tmp_PV := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / INT_TO_REAL(10 ** #tmp_VISU.DEC_PLACES);

Wie ist es richtig, ich komm da nicht weiter, da meine SCL-Kenntnisse noch etwas bescheiden sind. :confused:
 
Code:
#tmp_PV := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / INT_TO_REAL(10 ** #tmp_VISU.DEC_PLACES);
Versuch's mal mit 10.0 ** INT_TO_REAL(#tmp_VISU.DEC_PLACES) statt INT_TO_REAL(10 ** #tmp_VISU.DEC_PLACES).
Vermute mal, dass der Compiler nur daran erinnern will, dass der WerteBereich von INT beim Potenzieren sehr leicht überschritten werden kann.

PS:
Das hat nix mit SCL-Kenntnissen zu tun, sondern mit den WerteBereichen von INT, DINT, REAL.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen Dank, ja so funktioniert es. Die Problematik mit dem Wertebereich bei INT ist klar. Allerdings erschliesst mir nicht ganz, warum nun die Potenz in Real gewandelt, die richtige Lösung ist :p
 
Weil der Datentyp der ersten Variable im Ausdruck vorgibt mit welcher Basis weitergerechnet wird (oder so ähnlich). NICHT der Typ der zugewiesenen Variable.
Kommt mir persönlich auch auch total albern vor (definierte Fehlerfalle), ist angeblich aber bei allen Hochsprachen dieser Art schon immer so gewesen.

Wenn du den Baustein auf IEC-Prüfung stellst, bekommst du "härtere" Fehlermeldungen wenn bei den Typen was nicht passt. Aus meiner Sicht sollte man das immer tun, weil die Warnung schnell übersehen werden kann und das ganz doofe Fehler erzeugen kann und diese Siemens-Interpretation eben nicht immer logisch ist (Überraschung !).
 
Na ja, bei jeder Art von Automatik, sollte man eine Vorstellung davon haben, was sie kann und wie man sie beeinflussen kann. Das ist nicht speziell ein Siemens- oder SCL- oder Hochsprachen-"Problem".
Wie man durch ein Zuviel an Automatik zur Verzweiflung getrieben werden kann, kann man sehr gut in Excel durchleiden.
Du müsstest Dir im Klaren sein, dass in '10 ** #tmp_VISU.DEC_PLACES' beide Operanden vom Typ INT sind, denn Du wandelst das INT-Ergebnis der Operation explizit anschliessend von INT in REAL.
Wozu, wenn Du davon ausgehst, dass das Ergebnis bereits automatisch in REAL vorliegt??
Im INT kannst Du nur 10^-1 ... 10^0 ... 10^4 rechnen, denn bei 10^5 landest Du schon im Überlauf (100000 ist schon deutlich grösser als 32767) bzw. bei Ergebnissen, die ohnehin nur als 0 dargestellt werden können.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Die eigentliche Ursache ist, dass bei TIA das Ergebnis der Potenzfunktion vom Datentyp LREAL ist.

Das Ergebnis von "(10 ** #tmp_VISU.DEC_PLACES)" ist also vom Datentyp LREAL. Linke Seite vom Ausdruck ist REAL, also ist das Ergebnis des Ausdrucks auch LREAL. Das landet aber bei dir in einer REAL-Variable und dort geht Genauigkeit verloren.
 
Linke Seite vom Ausdruck ist REAL, also ist das Ergebnis des Ausdrucks auch LREAL.
??? Kannst Du das mal erläutern?
Mein Stand ist, das erster Variablentyp (Links ?) die Grundlage ansagt...

Und wenn das stimmt, finde ich genau diese Annahme eine dumme Annahme. Dann entweder hart Typkonflikt melden oder alles auf autom. auf ein sinnvolles Format wandeln (Ziel-Variable?). Aber den Grundgedanken erste Variable kann ich nicht nachvollziehen. Wenn das aber anders ist ....
 
??? Kannst Du das mal erläutern?
Mein Stand ist, das erster Variablentyp (Links ?) die Grundlage ansagt...

Die implizite Typkonvertierung verwendet den größten Datentyp des Ausdrucks, und konvertiert den kleinen Typ auf den großen (wenn die Typkonvertierung das hergibt) und das Ergebnis des Ausdrucks ist dann auch der größte Datentyp.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
:confused:
Wir hatten das hier auch schon mal anders.
Da kam die Meldung bei (ich hoffe, ich hab's noch richtig in Erinnerung)
DINT := 10 * DINT;
weil die führende 10 das Ergebnis auf INT festlegte und der 2. DINT deshalb den impliziten Genauigkeitsverlust hatte.

Bei
DINT := DINT * 10;
kam die Meldung dagegen nicht.

Trotzdem würde dann die Potenzgleichung beim TE implizit Genauigkeit verlieren.
Nur nicht erst bei der Zuweisung, sondern schon zwischendurch.

PS:
Die DINTs könnten auch REAL gewesen sein.
Demenz lässt da grüßen, sollte aber auch keine Rolle spielen.
 
Zuletzt bearbeitet:
Die eigentliche Ursache ist, dass bei TIA das Ergebnis der Potenzfunktion vom Datentyp LREAL ist.
D.h. der Compiler gibt nur eine milde Warnung heraus, obwohl die explizit angeforderte TypKonvertierung INT_TO_REAL mehr als total daneben gegriffen ist und sang und klanglos durch LREAL_TO_REAL ersetzt wird? Das ist vorsätzliche Irreführung. Ich bitte zu entschuldigen, dass ich zaghaft Siemens verteidigt habe. Da gehört draufgehauen! :ROFLMAO: ;)
 
Also ich hab auch eine Schmerzvolle Erinnerung das
c = a *b
was anders ist wie
c = b * a
wenn a Typ BYTE und c und B INT sind. Bei byte-overflow steht im 1. Fall dann in c nur das lowbyte des Ergebnisses. Ist aber 2 Jahre (V14) oder so her...

EDIT:
Ich habe es mit noch mal angeschaut.
Das war im Zusammenhang mit Konstanten, die unter 256 waren und nicht mit INT# davor.
Also sowas:
#varBYTE := 5;
#varINT := #varBYTE * 250; // Ergebnis : 226 !?!!? (LowByte von 1250 !)
#varINT := BYTE_TO_INT(#varBYTE) * 250; // Ergebnis : 1250
#varINT := #varBYTE * INT#250; // Ergebnis : 1250
#varINT := 5 * 250; // Ergebnis : 1250

Mit IEC-Prüfung übersieht man sowas nicht ...
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
#tmp_PV := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / INT_TO_REAL(10 ** #tmp_VISU.DEC_PLACES);
Versuch's mal mit 10.0 ** INT_TO_REAL(#tmp_VISU.DEC_PLACES) statt INT_TO_REAL(10 ** #tmp_VISU.DEC_PLACES).
Vielen Dank, ja so funktioniert es.
@gochtel
Meinst Du, daß dieser Code in TIA V16 ohne Warnungen übersetzt wird? :confused:
Code:
#tmp_PV := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / 10.0 ** INT_TO_REAL(#tmp_VISU.DEC_PLACES);
In TIA V15.1 erhält das ebenfalls die Compiler-Warnung wegen möglicherweise Genauigkeitsverlust!

Wie Thomas_v2.1 schon schrieb, ist das Problem daß implizit in LREAL gewandelt wird und danach einer REAL-Variable zugewiesen wird.

In TIA: Der Potenz-Ausdruck akzeptiert zwar Ganzzahl- und Gleitpunkt-Operanden, das Ergebnis ist aber immer Gleitpunkt. Wobei TIA da anscheinend etwas "variabel" ist, ob REAL oder LREAL.

Code:
[COLOR="#008000"]//mit TIA V15.1
//Der Potenz-Ausdruck akzeptiert Ganzzahl- und Gleitpunkt-Operanden, das Ergebnis ist immer Gleitpunkt.[/COLOR]

#tmp_RealVar := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / (10 ** #tmp_IntVar);
[COLOR="#008000"]// REAL := REAL / LREAL
// Warnung: Genauigkeit! bei Zuweisung LREAL-Ergebnis an REAL-Variable
// Nicht eindeutig! wird (10 ** INT) als INT oder LREAL gerechnet?[/COLOR]

#tmp_RealVar := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / [COLOR="#FF0000"]INT_TO_REAL[/COLOR](10 ** #tmp_IntVar);
[COLOR="#008000"]// REAL := REAL / INT_TO_REAL(LREAL)
// Warnung: Genauigkeit! bei impliziter Wandlung LREAL zu INT in der Klammer wegen unpassendem INT_TO_REAL[/COLOR]

[COLOR="#008000"]// Das soll die Lösung sein, die in TIA V16 ohne Warnung durchgeht?!?[/COLOR]
#tmp_RealVar := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / [COLOR="#FF0000"]10.0[/COLOR] ** INT_TO_REAL(#tmp_IntVar);
#tmp_RealVar := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / [COLOR="#FF0000"]10.0[/COLOR] ** #tmp_IntVar;
[COLOR="#008000"]// REAL := REAL / LREAL**REAL
// Warnung: Genauigkeit! bei Zuweisung LREAL-Ergebnis an REAL-Variable
// Problem ist die Konstante 10.0 die als LREAL angesehen wird[/COLOR]

[COLOR="#008000"]//Lösung: so wird in REAL gerechnet, ohne Compiler-Warnungen[/COLOR]
#tmp_RealVar := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / [COLOR="#0000FF"]REAL#10.0[/COLOR] ** INT_TO_REAL(#tmp_IntVar);
#tmp_RealVar := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / [COLOR="#0000FF"]REAL#10.0[/COLOR] ** #tmp_IntVar;

Harald
 
@gochtel
Meinst Du, daß dieser Code in TIA V16 ohne Warnungen übersetzt wird? :confused:

Code:
#tmp_PV := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / 10.0 ** INT_TO_REAL(#tmp_VISU.DEC_PLACES);
ja, da kommt keine Compilerwarnung.

Code:
[COLOR=#008000]//Lösung: so wird in REAL gerechnet, ohne Compiler-Warnungen[/COLOR]
#tmp_RealVar := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / [COLOR=#0000FF]REAL#10.0[/COLOR] ** INT_TO_REAL(#tmp_IntVar);
#tmp_RealVar := DINT_TO_REAL(STRING_TO_DINT(#STR_PV)) / [COLOR=#0000FF]REAL#10.0[/COLOR] ** #tmp_IntVar;
beide Lösungen funktionieren. aber kann ich bei der 2. Variante den Realwert mit INT Potenzieren? Wäre für mich so logischer (mathematich gesehen).
 
Zuletzt bearbeitet:
ja, da kommt keine Compilerwarnung.
Ah, da hat man wohl nun dem Compiler beigebracht, daß Gleitpunkt-Konstanten nicht immer LREAL sein müssen. Gab es vielleicht Beschwerden von Großkunden/Programmierern die sehr viel Arbeitszeit verschwenden wenn sie immer "REAL#10.0" anstatt "10.0" eintippen müssen? ;)

kann ich bei der 2. Variante den Realwert mit INT Potenzieren? Wäre für mich so logischer (mathematich gesehen).
Weil in SCL die Potenz-Funktion immer einen Gleitpunktwert als Ergebnis liefert, vermute ich, daß es auch in TIA gar keine Ganzzahl-Potenz gibt, daß zunächst Ganzzahl-Operanden immer automatisch/implizit in Gleitpunkt gewandelt werden und die Potenz immer in REAL oder LREAL gerechnet wird. Der "classic"-SCL-Compiler übersetzt so:
Code:
//SCL: rResult := rX ** iPotenz;

L #iPotenz
ITD
DTR
L #rX
LN
*R
EXP
T #rResult

Ob der TIA-SCL-Compiler etwas optimiert, falls die Potenz als kleine Ganzzahl-Konstante angegeben wird, weiß ich nicht. Der "classic"-SCL-Compiler optimiert z.B. a**2 ---> a*a

Harald
 
Zurück
Oben