# REAL - Wert wird abgerundet



## Nilzon (28 Dezember 2017)

Hallo liebe Gemeinde,

bitte verzeiht mir diese vermutlich saudumme Frage.
Ich komme hier grad gar nicht mehr klar.

Alles, was ich tun wollte ist, einen Rechenwert einer REAL-Variable zuzuweisen.
Aber ich bekomme immer nur Ganzzahlen.

Könnte ihr mir bitte kurz auf die Spünge helfen?

test ist meine REAL-Variable...

test := 1/2; //liefert mir 0 für test
test := 2/3; //liefert mir 0 für test
test := INT_TO_REAL(2)/INT_TO_REAL(3); //liefert mir 0.6666667 für test

Ich bin im e!Cockpit fast verzweifelt und hab das dann in CoDeSys v2.3 probiert, mit demselben Ergebnis. 
Woran liegt das?
Und bevor der Shitstorm losgeht, ich habe wirklich gesucht. Aber wonach willste denn da suchen?
Sowas ist doch so banal, dass man da überhaupt gar nix findet.

Vielen lieben Dank vorab für Eure Hilfe!

Grüße
Nils


----------



## Ralle (28 Dezember 2017)

Versuch bitte mal:

test := 1.0/2.0;


----------



## Nilzon (28 Dezember 2017)

Hallo Ralle,

das funktioniert, vielen Dank für den Tipp! 
Aber gestatte mir doch noch bitte die Frage: Was steckt dahinter? 

In der Hilfe steht unter DIV

var1 := 8/2;

Das funktioniert, weil da sowieso ne Ganzzahl rauskommt, hab ich jetzt verstanden.
Ist vielleicht auch nicht das bestgewählte Beispiel muss ich ja mal sagen, weil ich daraus abgeleitet hatte, dass das andere ja auch gehen müsste.

Und wenn ich mal nehme:
var1 : INT :=8;
var2 : INT :=3;

test := var1/var2;
Dann kommt da 2 raus, wie oben

Und bei
test := var1/3.0;
Da kommt 2.666667 raus, also geht nur INT/INT nicht?
Folglich muss ich immer darauf achten (z.B. bei test := var1/var2; ) die var1 und var2 als REAL zu deklarieren...

Nochmals vielen Dank für die (im Ãœbrigen unglaublich schnelle) Lösung. 
Ich würde mich freuen, noch zu lernen, warum das so ist. 
Falls es eine Möglichkeit gibt, sich sowas beizubringen (Literatur / Website), dann sind diese Tipps auch sehr willkommen. 

Viele Grüße,
Nils


----------



## oliver.tonn (28 Dezember 2017)

Hallo Nils,
Ralles Antwort enthält schon die Lösung zu Deinem Problem. Von mir kommt jetzt noch die Erklärung dazu warum das so ist. Bei den Codesys Derivaten zu dem auch e!Cockpit gehört werden direkt im Code vorgegebene Zahlen anhand dessen wie sie angegeben sind unterschieden. Damit eine Fließkommzahl ohne Nachkommastellen von Codesys erkannt wird muss diese trotzdem mit mindestens einer Nachkommastelle angegeben werden. Wie Ralle schon richtig schrieb, bei einer 1 also 1.0 und entsprechend bei einer 2 dann 2.0 . Geschieht dies nicht interpretiert Codesys diese Zahl als Ganzzahl und rechnet mit diesen auch entsprechend. Eine Division zweier Ganzzahlen ergibt auch wieder eine Ganzzahl und soweit das Ergebnis der Division kleiner 1 ist kommt bei einer Ganzzahl eine 0 raus. Durch die implizite Konvertierung wird dieses Ergebnis nun in eine Fließkommazahl gewandelt und in test geschrieben, bleibt dort aber auch 0.


----------



## Nilzon (28 Dezember 2017)

Hallo Oliver,

vielen Dank für die ausführliche Erklärung. 
Es war sehr interessant, das so im Detail zu erfahren.

Bei der Aussage


oliver.tonn schrieb:


> Eine Division zweier Ganzzahlen ergibt auch wieder eine Ganzzahl


würde wahrscheinlich so mancher Mathelehrer widersprechen  aber da lag eben mein Verständnisproblem. 
Zudem habe ich mich verleiten lassen, bei ST die Gepflogenheiten anderer Programmiersprachen vorauszusetzen...

Toll, dass es hier so eine fundierte Unterstützung gibt!

Viele Grüße,
Nils


----------



## Thomas_v2.1 (28 Dezember 2017)

Die komplette Anweisung wird zuerst in die einzelnen Ausdrücke zerlegt. Die einzelnen Ausdrücke werden separat mit ihren Datentypen behandelt. Erst wenn eine Seite eines Ausdrucks einen unterschiedlichen Datentyp aufweist, wird ggf. eine Datentypkonvertierung vorgenommen

Nur mit den Datentypen sieht deine Anweisung so aus:

REAL := INT / INT;

Die Division wird auf dem Datentyp INT gerechnet. Da beide Operatoren vom Typ INT sind ist auch das Ergebnis der Division vom Typ INT. Nach diesem Schritt steht dort sozusagen:
REAL := INT;

Und hier erfolgt von Codesys eine implizite (d.h. automatische) Typkonvertierung von kleineren Typ (INT) zum größeren (REAL). Als wenn du schreiben würdest:
REAL := INT_TO_REAL(INT);

Das Verhalten ist bei jeder Operation so. Hast du z.B. eine Anweisung wie:

realVar := 8.5 / 2;

Dann würden die Datentypen erkannt als:
REAL := REAL / INT;

Und da erkennt der Compiler, dass die Datentypen der Division unterschiedlich sind und fügt auch hier eine erlaubte implizite Datentypkonvertierung vom kleineren (INT) zum größeren (REAL) Datentyp durch. Als wenn du explizit schreiben würdest:
realVar := 8.5 / INT_TO_REAL(2);
Dann wird die Division gleich mit zwei Real-Zahlen durchgeführt.

Ein untypisiertes Literal wie 2 oder 123 wird immer als Datentyp Integer erkannt. Ein untypisiertes Literal wie 8.5 immer als REAL.
Es gibt auch typisierte Literale wie INT#2 oder DINT#2 oder REAL#2 (hoffe das ist bei Codesys so erlaubt), damit gibst du direkt den Datentyp der Konstante an.

Andersherum gibt es keine implizite Konvertierung. Hast du beispielsweise

INT := REAL / REAL;

Dann erhältst du eine Fehlermeldung, weil das Ergebnis der Division auch ein REAL ist, und noch ohne explizite Konvertierung einem INT zugewiesen werden kann.


----------



## oliver.tonn (28 Dezember 2017)

Immer wieder gerne, übrigens es gibt keine Dummen Fragen, nur dumme Antworten. Soweit der Fragensteller nicht die komplette Erledigung seiner Hausaufgabe oder Abnahme seiner Arbeit erwartet und selber an der Lösung im Rahmen seiner Möglichkeiten mitarbeitet helfen wir hier gerne jedem weiter.


----------



## oliver.tonn (28 Dezember 2017)

Hallo Thomas,


Thomas_v2.1 schrieb:


> Es gibt auch typisierte Literale wie INT#2 oder DINT#2 oder REAL#2 (hoffe das ist bei Codesys so erlaubt), damit gibst du direkt den Datentyp der Konstante an.


ja, ist in Codesys, zumindest in TwinCAT, erlaubt. Kannte ich auch noch nicht, wieder was gelernt, danke.


----------



## Nilzon (29 Dezember 2017)

Hallo nochmal,

auch Dir, Thomas, vielen Dank. 
Ich habe das mal alles ausprobiert und einiges dabei gelernt.

Ich bin gerade dabei, eBus-Telegramme auszulesen und zu senden.
EBus ist ein in der Heizungstechnik verwendetes Protokoll. 
Es gab auch in diesem Forum mal Ansätze, die aber alle im Sande verlaufen haben. 
Aber wenn man hier so eine tolle Unterstützung bekommt, dann werde ich mir gerne auch die Mühe machen und meine Lösung dort dokumentieren.

Schöne Grüße und einen guten Rutsch!
Nils


----------

