LREAL Rounding

pawel12345

Level-1
Beiträge
58
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

weiß jemand, ob es eine fertige Funktion gibt um LREAL zu runden? In einem Projekt müssen wir die LREALs verwenden und die entsprechend runden. Es gibt viele Funktionen die z.B OSCAT_BASIC.ROUND die eine reelle Zahl runden können aber ich habe nichts für LREAL gesehen. Wir wollen auch eine Zahl mit genau vorgegebene Anzahl von
Nachkommastellen ins Cloud verschicken. Da braucht man auch eine Funktion wie zB TRUC(), die auch für Real geeignet ist. Hat jmd eine Idee wie man da vorgehen kann ?


Grüße
Pawel
 
Ich habe jetzt ein kleines Programm geschrieben und scheint einigermaßen zu funktionieren. Ich würde aber trotzdem gerne eine gut getestete Standardfunktion verwenden. (Falls es eine gibt)


//Runden auf 3 Nachkommastellen : Bei der Umwandlung wird die Zahl automatisch gerundet und die restliche Nachkommastellen sind weg
PROGRAM PLC_PRG
VAR
diTest : DINT;
lrTEST : LREAL;
lrResult : LREAL;
END_VAR



diTest :=LREAL_TO_DINT(lrTEST * EXPT(10,3));
lrResult :=DINT_TO_LREAL(diTest)/EXPT(10,3);
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wir wollen auch eine Zahl mit genau vorgegebene Anzahl von Nachkommastellen ins Cloud verschicken.
Das geht nicht als LREAL. LREAL hat prinzipiell immer soviele Nachkommastellen, wie die nächstliegende als LREAL darstellbare Zahl eben hat. Da hilft auch ein Abschneiden von Nachkommastellen oder Runden nicht. Nur in der Anzeige (als Zeichenfolge) kann man eine bestimmte Anzahl Nachkommastellen festlegen/ausgeben.

Zahlen mit bestimmter Anzahl Nachkommastellen ausgeben/übergeben kann man nur als Zeichenfolge oder String, oder als Ganzzahl mit Multiplikator wo das Dezimalkomma sitzen soll.

Harald
 
Hallo @PN/DP

vielen Dank für die schnelle Antwort.

Naja, es geht eher darum dass die Zahl gerundet wird und dann nur zB drei Nachkommastellen (ungleich 0) hat und Rest "0". Dann werden die restliche "0" in der Cloud nicht angezeigt.
Mit dem Programm was ich da gepostet habe, schein "ok" zu funktionieren.



Grüße
Pawel
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Mit dem Programm was ich da gepostet habe, schein "ok" zu funktionieren.
In der SPS-Programmierung sollte man keinen Code verwenden, der mit ein paar Testfällen zu funktionieren "scheint". Besonders wenn man nicht genau weiß was man tut und was der Code tut.
Wie groß können Deine LREAL-Zahlen werden? Der Code "funktioniert" außerdem nur mit Werten bis ca. 2 Millionen.

Wenn der Code nur für Anzeigezwecke ist, kann man wohl mit leben. Dann schreibe den Code aber wenigstens nicht so umständlich. Ein simples Multiplizieren und Dividieren mit 1000 tut es viel effizienter und vor allem lesbarer:
Code:
diTest :=LREAL_TO_DINT(lrTEST * 1000.0);
lrResult :=DINT_TO_LREAL(diTest) / 1000.0;

Wo in der "Cloud" werden die Zahlen angezeigt? Ein REAL oder LREAL mit Nachkommastellen ist (fast) immer gerundet. Weiß die "Cloud" daß die Zahlen auf 3 Nachkommastellen gerundet sein sollen?

Harald
 
Zuletzt bearbeitet:
Meine Meinung nach macht das Nachkommastellenabschneiden nur Sinn, wenn man auf den Datentyp String setzt. Dem LREAL ist es absolut egal, wieviele Kommastellen er hat. Der belegt immer 64bit im Speicher.

Euch wird es um die Lesbarkeit gehen, nur das macht man nicht in der SPS, sondern im HMI. Eure Cloud hat warscheinlich auch so etwas wie ein Frontend, weil der Cloud selbst ist es auch egal, wieviel Nachkommastellen der Wert hat.

Wenn Ihr die Anzeige im Frontend nicht beeinflussen könnt, kann man die Werte als String vorbereiten und in die Cloud senden. Ich konnte nicht herauslesen, was für ein System ihr habt, bei Beckhoff TwinCAT würde das hiermit gehen: FB_FormatString https://infosys.beckhoff.de/content...es_fb_formatstring.htm?id=1285303247796994588

Dann müsst Ihr aber auf das länderspezifischen Dezimaltrennzeichen achten.

Eine andere Möglichkeit die mir noch in der SPS einfällt, wäre:
Code:
Gerundet := DINT_TO_LREAL(LREAL_TO_DINT(Wert * 100.0)/100);
100 für zwei Nachkommastellen.


Wobei man beachten muss, dass aus 1.10 dann 1.1 wird. Und unter Umständen auch mal wieder 1.09999999999999999.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie groß können Deine LREAL-Zahlen werden? Der Code "funktioniert" außerdem nur mit Werten bis ca. 2 Millionen.
Wenn die Steuerung LREAL kann, dann kann sie bestimmt auch LINT. Dann sollte man auch das Runden über LINT anstatt DINT machen.

Harald
 
Mein Ziel ist es nicht ein LREAL zu haben was zB genau 3 Nachkommastellen hat und dann nichts. Ich zeige das ganze auf einem Beispiel. Wir verschicken drei Zahlen in unsere Cloud.
1. 1.123456789 (REAL)
2. 2.345000000 (LREAL)
3. 2.344999999 (LREAL);

1. --> in der Cloud bekommen wir genau diese Zahl mit alle Nachkommastellen also 1.123456789. Das will der Kunde nicht sehen. Der will bestimmtes Anzahl an Nachkommastellen sichtbar haben
2. --> in der Cloud wird 2.345 angezeigt, da die LREAL automatisch die restliche Nullen abschneidet (beim REAL passiert das nicht)
3. --> die Cloud zeigt 2.344999999 an.

Deswegen ist es wichtig, dass diese Zahlen mit bestimmte Anzahl an Nachkommastellen verschickt werden..


In der SPS-Programmierung sollte man keinen Code verwenden, der mit ein paar Testfällen zu funktionieren "scheint". Besonders wenn man nicht genau weiß was man tut und was der Code tut.
Wie groß können Deine LREAL-Zahlen werden? Der Code "funktioniert" außerdem nur mit Werten bis ca. 2 Millionen.

Wenn der Code nur für Anzeigezwecke ist, kann man wohl mit leben. Dann schreibe den Code aber wenigstens nicht so umständlich. Ein simples Multiplizieren und Dividieren mit 1000 tut es viel effizienter und vor allem lesbarer:
Code:
diTest :=LREAL_TO_DINT(lrTEST * 1000.0);
lrResult :=DINT_TO_LREAL(diTest) / 1000.0;

Wo in der "Cloud" werden die Zahlen angezeigt? Ein REAL oder LREAL mit Nachkommastellen ist (fast) immer gerundet. Weiß die "Cloud" daß die Zahlen auf 3 Nachkommastellen gerundet sein sollen?

Harald
Nein, das ist eine Funktion die bis drei Nachkommastellen funktionieren sollte also in der SPS steht dann EXPT(10,uiDecimal);

@PN/DP
Ja die Funktion muss bis eine Millione funktionieren, sonst bei größeren Zahlen kommt es zum Überlauf.
 
Lass uns mal die Begrifflichkeiten auseinandernehmen.

Also eine Cloud ist ja erst einmal nur ein Datenspeicher. Und euer Kunde sägt ja nicht den Speicher auf und schaut dort rein und sieht da irgendwelche Nachkommastellen. Ihr habt da ja irgendwie eine Datensicht, ein Frontend oder so etwas. Klärt uns mal auf, was ihr da benutzt. Was für Möglichkeiten der Formatierung gibt es da?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Nein, das ist eine Funktion die bis drei Nachkommastellen funktionieren sollte also in der SPS steht dann EXPT(10,uiDecimal);

Kann es sein, dass Ihr da irgendetwas in Expotential-Schreibweise versucht und die Mantisse und den Exponent getrennt übertragt? Und dann in der Ansicht wieder zusammen setzen wollt?
 
Nein, das ist eine Funktion die bis drei Nachkommastellen funktionieren sollte also in der SPS steht dann EXPT(10,uiDecimal);
Die Funktion EXPT(10,3) liefert 1000 zurück, wo ist da jetzt der Unterschied zu Haralds Vorschlag? Übrigens wenn Du weiterhin EXPT nutzen möchtest solltest Du "10.0, 3.0" nutzen und nicht "10, 3" das wäre sauberer, letzteres wird vom Compiler nämlich als Ganzzahl interpretiert und nicht als LREAL.
 
Zuletzt bearbeitet:
Mein Ziel ist es nicht ein LREAL zu haben was zB genau 3 Nachkommastellen hat und dann nichts. Ich zeige das ganze auf einem Beispiel. Wir verschicken drei Zahlen in unsere Cloud.
1. 1.123456789 (REAL)
2. 2.345000000 (LREAL)
3. 2.344999999 (LREAL);

1. --> in der Cloud bekommen wir genau diese Zahl mit alle Nachkommastellen also 1.123456789. Das will der Kunde nicht sehen. Der will bestimmtes Anzahl an Nachkommastellen sichtbar haben
2. --> in der Cloud wird 2.345 angezeigt, da die LREAL automatisch die restliche Nullen abschneidet (beim REAL passiert das nicht)
3. --> die Cloud zeigt 2.344999999 an.

Deswegen ist es wichtig, dass diese Zahlen mit bestimmte Anzahl an Nachkommastellen verschickt werden..
Nochmal: man kann einen LREAL-Wert nicht mit einer bestimmten Anzahl Nachkommastellen verschicken. Man kann nur die Ausgabe als Text (String, Zeichenfolge) so formatieren, daß (nur) eine bestimmte Anzahl Nachkommastellen angezeigt wird.

Man kann LREAL-Werte runden auf eine bestimmte Anzahl Nachkommastellen, doch das gerundete Ergebnis enthält in den meisten Fällen wieder eine Zahl die mehr als die gewünschte Anzahl Nachkommastellen enthält. Ganz einfach deshalb, weil in LREAL nicht jeder beliebige Wert darstellbar ist und immer auf den nächstliegenden darstellbaren Wert gerundet wird.

Zu Deinem Beispiel:
Wenn Du 2.344999999 durch Deinen oder meinen Rundungscode schickst, dann ist das Ergebnis (wahrscheinlich) 2.3449999999999997513100424 - das Runden hat also nichts gebracht:
Code:
lrTEST := 2.344999999;
diTest :=LREAL_TO_DINT(lrTEST * 1000.0);   ---> ergibt vermutlich 2345
lrResult :=DINT_TO_LREAL(diTest) / 1000.0; ---> ergibt vermutlich 2.3449999999999997513100424
Egal ob man nun höchst umständlich mit EXPT(10,3) rechnet (*) oder gleich die Konstante 1000.0 verwendet, das Ergebnis wird einer LREAL-Variable zugewiesen und die enthält danach den Wert 2.3449999999999997513100424

(*) Vielleicht ist der ST-Compiler auch so intelligent wie ich ;) und erkennt, daß er den Ausdruck EXPT(10,3) durch die Konstante 1000.0 ersetzen kann?


Wir verschicken drei Zahlen in unsere Cloud.
[...]
2. 2.345000000 (LREAL)
[...]
2. --> in der Cloud wird 2.345 angezeigt, da die LREAL automatisch die restliche Nullen abschneidet (beim REAL passiert das nicht)
Daß die Cloud 2.345 anzeigt muß einen anderen Grund haben - vermutlich rundet die selber die Ausgabe auf höchstens 9 Nachkommastellen?
Du denkst, Du verschickst 2.345000000, tatsächlich wird aber 2.3449999999999997513100424 oder 2.3450000000000001953992523 verschickt.

Bitte beschäftige Dich mit den Grundlagen von Gleitkommazahlen nach IEEE 754, siehe die Links in Beitrag #7

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Daß die Cloud 2.345 anzeigt muß einen anderen Grund haben - vermutlich rundet die selber die Ausgabe auf höchstens 9 Nachkommastellen?
Du denkst, Du verschickst 2.345000000, tatsächlich wird aber 2.3449999999999997513100424 oder 2.3450000000000001953992523 verschickt.

Genau. Das Problem ist im Frontend der Cloud zu lösen. Vielleicht kann uns der TE mal über die technischen Spezifikationen der Cloud und wie die Daten angezeigt werden aufklären. In der SPS macht das einfach keinen Sinn.
 
Daß die Cloud 2.345 anzeigt muß einen anderen Grund haben - vermutlich rundet die selber die Ausgabe auf höchstens 9 Nachkommastellen?
Das hatte der TE in #4, soweit ich das richtig verstanden habe, schon geschrieben, das Frontend blendet ab der Stelle wo die Nachkommastellen nur noch Nullen enthalten automatisch aus.
Hilft aber alles nichts, da seine Idee nur manchmal funktionieren würde.
 
Zu dem EXPT(10,3) und 1000. Das ist doch klar ???
Wie schon geschrieben, steht im Programm EXPT(10,uiDecimal) damit diese Funktion für verschiedene Anzahl an Nachkommastellen verwendet werden kann.


Zu dem lrResult := DINT_TO_LREAL(diTest)/ 1000.0 Es ergibt genau 2.345. Ich habe mir in Table-Storage Rohdaten angeschaut und es sieht sehr gut aus. Wieso es so ist? Weiß ich nicht. Mit diese Methode werden jetzt aber richtige Werte in der Cloud angezeigt.

Vielen Dank für alle Antworten !!!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zu dem lrResult := DINT_TO_LREAL(diTest)/ 1000.0 Es ergibt genau 2.345. Ich habe mir in Table-Storage Rohdaten angeschaut und es sieht sehr gut aus. Wieso es so ist? Weiß ich nicht.
Weil es mit der Zahl 2.345 klappt, mit anderen, wie Harald in #14 demonstriert hatte aber wird es nicht klappen, weswegen Du, wie schon mehrfach empfohlen, die Daten in einem String ablegen solltest.
Übrigens nochmals eine Cloud ist einfach ein Speicher und kann nichts anzeigen, zum Anzeigen nutzt Du dann irgendein Frontend.
Lag ich übrigens mit meiner Vermutung richtig, dass Dein Frontend die Nachkommastellen abschneidet sobald nur noch Nullen folgen?
 
Ich habe das nicht mit eine Zahl getestet sondern ein kleines Testprogramm geschrieben und dann viele Verschiedene Testzahlen verschickt. Ich kann die Zahlen als String nicht verschicken, da wir die Daten später bearbeiten müssen und das wollen die Jungs die sich um die Platform kümmern nicht.

Ja, wenn die Nullen am Ende stehen werden die abgeschnitten. :cool:
 
Zu dem lrResult := DINT_TO_LREAL(diTest)/ 1000.0 Es ergibt genau 2.345.
Das Ergebnis kann nicht "genau 2.345" sein, weil es 2.345 als LREAL gar nicht gibt, weil 2.345 gar nicht als LREAL dargestellt werden kann. Da bescheixxt Dich Dein Anzeigeprogramm. Oder in dem "Table-Storage" (Was ist das?) sind die Zahlen nicht LREAL, sondern ein anderer Datentyp?

Erkläre uns (und Dir selber): Wie soll das 64-Bit-Bitmuster des LREAL-Wertes "genau 2.345" aussehen? Kannst Du Dir das Ergebnis der Berechnung (den Wert in lrResult) hexadezimal anzeigen lassen?
Das Ergebnis kann nur 2.3449999999999997513100424 oder 2.3450000000000001953992523 sein, dazwischen gibt es als LREAL keinen Wert. Und da kommen nach dem 2.345 nicht nur noch Nullen sondern auch noch ein paar Nachkommastellen <> 0. Wegen irgendeiner Regel schneidet das Anzeigeprogramm bei der Anzeige diese Nachkommastellen ab. Wenn man diese Regel nicht kennt und bewußt ausnutzt, dann ist jede "scheint zu funktionieren" Zahlenmanipulation unglaublich unwissend und naiv ...

Harald
 
Zurück
Oben