PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme mit der REAL_TO_INT Funktion



Superfly
13.05.2008, 16:28
Hallo!!

Ich möchte eine REAL-Variable in einen String umwandeln. Soweit funktioniert diese Funktion auch, aber wenn z.B. in der Variablen steht 4.3 dann bekomme ich als Ergebniss '4.300000021353234'

Weiß jemand wie das vermieden werden könnte??:confused:
Möchte ja als Antwort: '4.3' im String stehen haben.

Ich habe auch die Funktion FB_FormatString einmal getestet und das Beispiel implementiert. Wenn man nun hier REAL-Variablen verwendet und z.B. 0.1 immer aufaddiert kommt plötzlich auch ein Fehler bei der Addition zustande!!
Kennt jemand diese Fehler??

Schöne Grüße!!

MTec
13.05.2008, 16:38
Hallo,

wie wäre es anstelle von "REAL_TO_INT" mit "REAL_TO_STRING"?


LD 4.3
REAL_TO_STRING
ST HM_STRING


Viele Grüße
MTec

Larry Laffer
13.05.2008, 16:39
... das sind die Tücken der REAL-Zahlen ...

Mein Vorschlag wäre hier : auf INT (oder DINT) ausweichen. Bei einer Nachkommastelle multiplizierst du mit 10, machst eine INT daraus, wandelst diese in einen STRING (wenn es denn unbedingt ein STRING sein muss) und schiebst hinterher an der 2. Stelle von hinten das Komma in den STRING ein ...

Eine Art "PRINT USING"-Funktion gibt es da meines Wissens nicht ...

Gruß
LL

Superfly
13.05.2008, 16:48
wie wäre es anstelle von "REAL_TO_INT" mit "REAL_TO_STRING"?Sorry! Die Überschrift ist falsch! Sollte natürlich REAL_TO_STRING heißen!


das sind die Tücken der REAL-Zahlen ...Warum werden diese auch falsch addiert?



Mein Vorschlag wäre hier : auf INT (oder DINT) ausweichen. Bei einer Nachkommastelle multiplizierst du mit 10, machst eine INT daraus, wandelst diese in einen STRING (wenn es denn unbedingt ein STRING sein muss) und schiebst hinterher an der 2. Stelle von hinten das Komma in den STRING ein ...
Wie kann man dhier am besten ein Zeichen einfügen?

MTec
13.05.2008, 18:34
Wie kann man dhier am besten ein Zeichen einfügen?

Das könnte beispielsweise so aussehen:


PROGRAM PLC_PRG
VAR
HM_StringResult: STRING;
HM_StringLength: INT;
HM_CommaPos: INT;
END_VAR



(* String erzeugen *)
LD +123456 (*Ergebnis in DINT --> vorher für 2 Nachkommastellen mit 100 multipliziert *)
DINT_TO_STRING
ST HM_StringResult

(* Stringlänge ermitteln *)
LD HM_StringResult
LEN
ST HM_StringLength
(* Nachkommastellen berechnen *)
SUB 2
ST HM_CommaPos

(* Punkt in String einfügen *)
LD HM_StringResult
INSERT '.',HM_CommaPos
ST HM_StringResult


Der Feinschliff fehlt noch (z.B. auswerten von Werten < 10), aber Du möchtest ja auch noch etwas zu tun haben... :D

Viele Grüße
MTec

trinitaucher
13.05.2008, 20:59
...wenn z.B. in der Variablen steht 4.3 dann bekomme ich als Ergebniss '4.300000021353234'

... Wenn man nun hier REAL-Variablen verwendet und z.B. 0.1 immer aufaddiert kommt plötzlich auch ein Fehler bei der Addition zustande!!
Kennt jemand diese Fehler??
Das liegt an der internen Abbildung der REAL-Werte. Aufgrund derer Darstellung im Speicher mit "Exponent" und "Mantisse" (Grundlagen Informatik) sind nur ganz bestimmte Werte möglich, aber NIE der gesamte Wertebereich mit allen Nachkommastellen. So kann man z.B. eine riesige Zahl mit Nachkommastellen bilden, aber dann keine klitzekleine Zahl hinzuaddieren... is halt so.

Ich möchte damit nur sagen, dass der Wertebereich nie vollkommen durchgängig ist (wie z.B. beim Int: -32768...32767), sondern nur als "ca." mit Ober- und Untergrenzen angegeben werden kann.

Zur String-Umwandlung:
1. Bilder den String (...TO_STRING)
2. Durchsuche ihn z.B. mit einer Schleife bis zum Komma
3. Lesen n Nachkommastellen weiter
4. Die gesammelten Zeichen sind dann dein Ergebnis als neuer String
:cool:

MTec
14.05.2008, 07:58
Wenn man nun hier REAL-Variablen verwendet und z.B. 0.1 immer aufaddiert kommt plötzlich auch ein Fehler bei der Addition zustande



Das liegt an der internen Abbildung der REAL-Werte. Aufgrund derer Darstellung im Speicher mit "Exponent" und "Mantisse" (Grundlagen Informatik) sind nur ganz bestimmte Werte möglich, aber NIE der gesamte Wertebereich mit allen Nachkommastellen. So kann man z.B. eine riesige Zahl mit Nachkommastellen bilden, aber dann keine klitzekleine Zahl hinzuaddieren... is halt so.



Also ich bin zwar kein Informatiker, aber 4.3 + 0.1 ergibt bei mir auch nach der Umwandlung in String noch '4.4'. Wenn dem nicht so wäre, würde mir das ganz schön zu denken geben... :s17:


LD 4.3
ADD 0.1
ST TestReal
REAL_TO_STRING
ST TestString (*--> TestString = '4.4'*)


Viele Grüße
MTec

Superfly
14.05.2008, 12:48
Also ich bin zwar kein Informatiker, aber 4.3 + 0.1 ergibt bei mir auch nach der Umwandlung in String noch '4.4'. Wenn dem nicht so wäre, würde mir das ganz schön zu denken geben... :s17:


Bei der Funktion
Real:=Real+0.1 habe ich aber nicht wie anzunehmen 0.8 sondern 0.8000001 die Zahlen vorher sind korrekt?? Wenn man nun die Task ablaufen läst sind fast immer vier Nachkommastellen vorhanden!!

Das sollte so nicht sein! Ein Rechner der nicht rechnen kann??

MTec
14.05.2008, 13:48
Man lernt doch nie aus. Jetzt kann ich Dein "REAL"-Problem und das Posting von trinitaucher auch nachvollziehen. ;)

Wie wäre es wenn Du generell in ganzen Zahlen rechnest und nur zur Ausgabe des Strings die Kommastelle einfügst?


LD RealDemo
ADD 1.0
ST RealDemo

LD RealDemo
DIV 10.0
REAL_TO_STRING
ST StringDemo

Zottel
14.05.2008, 14:39
0.1 = 1/10 ist im Zweiersystem eine nicht abbrechende Dezimalzahl: 0,000011001100110011....
Da die Länge der Mantisse begrenzt ist, kann 0.1 einfach nicht exakt dargestellt werden, genauso wenig wie 1/3 oder 1/7 im Zehnersystem.

trinitaucher
14.05.2008, 15:37
0.1 = 1/10 ist im Zweiersystem eine nicht abbrechende Dezimalzahl: 0,000011001100110011....
Da die Länge der Mantisse begrenzt ist, kann 0.1 einfach nicht exakt dargestellt werden, genauso wenig wie 1/3 oder 1/7 im Zehnersystem.
Danke für das Beispiel. So in etwa meinte ich das :cool:

Für Details schaut mal in Lehrbücher zu Grundlagen der Informatik. Hängt alles von der internen Abbildung der Zahlen ab.
Ich versuche immer wo es geht ganzzahlige Datentypen zu verwenden (z.B. DINT), um eben solchen Problematiken aus dem Weg zu gehen.

Scrat
30.05.2008, 16:23
Hallo Leute,

das Ganze geht auch viel einfacher. Nutz einfach die Funktion LREAL_TO_FMTRSTRING. Damit wird die Variable in einen definierten Zustand gebracht. Die Zahl in den Parametern gibt die Anzahl der Nachkommastellen an, und die boolsche Variable gibt an ob die letzte Ziffer gerundet werden soll.

Beispiel:
sErgebnis := LREAL_TO_FMTRSTRING(rMesswert, 4, TRUE);


Gruß Benjamin

gravieren
30.05.2008, 18:35
@Scrat


sErgebnis := LREAL_TO_FMTRSTRING(rMesswert, 4, TRUE);

Schön, welches System hat den diese Funktion ?


Ich verwende die www.OSCAT.DE (http://www.OSCAT.DE) --> REAL_TO_STRF

Verfügbar:
Step 7
CoDeSys
TwinCat
PC WorX
MULTIPROG

Also ein paar hunder Systeme.

Andere Systeme sind anpassbar, da Quellcode beiliegend.




REAL_TO_STRF konvertiert einen REAL-Wert in einen STRING mit einer festen Anzahl von Nachkommastellen N. Bei der Konvertierung wird ausschließlich in Normales Zahlenformat XXX.NNN umgewandelt. Bei der Umwandlung wird IN auf N Stellen nach dem Komma gerundet und dann in einen Stringmit dem Format XXX.NNN gewandelt. Wenn N = 0 wird die REAL Zahl auf 0 Stellen hinter dem Komma gerundet und das Ergebnis als Integer ohne Punkt und Nachkommastellen ausgegeben. Wenn die Zahl IN kleiner ist als mit N Nachkommastellen erfasst werden können wird eine Null ausgegeben. Die Nachkommastellen werden immer auf N Stellen mit Nullen aufgefüllt. Die maximale Länge der Zeichenkette beträgt 20 Stellen.
Beispiel:REAL_TO_STRF(3.14159,4) = '3.1416'
REAL_TO_STRF(3.14159,0) = '3'
REAL_TO_STRF(0.04159,3) = '0.042'
REAL_TO_STRF(0.001,2) = '0.00'

Scrat
30.05.2008, 22:57
Beckhoff TwinCAT hat diese Funktion.
Ich weiß jetzt grad aber nicht auswendig in welcher Libary das drin ist. Ist aber in einer der Standard Libarys drin.

Gruß Benjamin

gravieren
31.05.2008, 08:16
ScratBeckhoff TwinCAT hat diese Funktion.
Ich weiß jetzt grad aber nicht auswendig in welcher Libary das drin ist. Ist aber in einer der Standard Libarys drin.


Das erinnert mich an die "guten Alten" - Basic Zeiten.

(Interpreter, Compiler von einer Programiersprache)

Da gabs QBasic, VCBasic, XBasic, Basic . . .

Jeder hatte so seine eigenen, Funktionen und Erweiterungen.

Fand man mal einen QUellcode von Basic, brachte man den nicht so "OHNE weiteres" zu laufen.


Das war für mich ein Hauptgrund, von ca. 20 Jahren zu "C" zu wechseln.

Das erklärt auch meine Abneigung von Nicht-Standartisierten Erweiterungen für die SPS-Welt.

ALSO:
Entweder Quelltextoffen oder Standartisiert.
Auf eine Funktion, die z.b.nur Beckhoff hat würde ich nicht aufsetzen.

Entweder "selber schreiben" oder "portablen Code" suchen.

Meine Lösung aktuell --> www.oscat.de (http://www.oscat.de)

Wobei die Lösung für jeden ganz anders aussehen kann.

P.S:
Unser GLT in der Firma (Projekt grösstenteils auswärtsbetreut)
Für das Gebäudeleitsystem wurde Wago bei uns ausgewählt.
Es werden die Wago-Libs verwendet.
(Entgegen meinem anraten auf "oscat")
Nun sollen für 2 "kritische" Anwendungen "S7-300 .. PN"-CPUs verwendet werden.
Jetzt fallen die Unterkiefer bis auf den Boden.
Mal schauen wie es weitergeht.

drfunfrock
31.05.2008, 13:42
Was ist eigentlich der Grund, dass plötzlich zwischen Technologien dh. hier zwischen zwei SPS-Anbietern so wilkührlich gewechselt wird?

gravieren
31.05.2008, 14:12
@drfunfrock


Was ist eigentlich der Grund, dass plötzlich zwischen Technologien dh. hier zwischen zwei SPS-Anbietern so wilkührlich gewechselt wird?

Kann ich nicht genau sagen.

Ich würde vermuten Kundenbindung.
Jeder hat z.b. einen eigenen PID-Regler.

Mal mehr, mal weniger funktionen.

Verwendest du die Beckhoff-Lib, so scheiden alle anderen Target aus.
Warum sollte auch Beckhoff für Wago, Siemens, Elrest ... programmieren.


Der Ansatz von CoDeSys ist eigentlich SUPER.
Eine Programmierumgebung, über 200 Hersteller vereinigen.


Leider gibt es nur wenige CoDeSys-eigenen Bibliotheken.
Die, die es gibt sind Quelltext-offen.


Das OSCAT-Team will diesen Zustand verbessern.
Quasi ein "Linux" für die SPS-Welt.

Sogar NICHT-CoDeSys Systeme laufen mit dieser Bibliothek.

z.b. Siemens Step 7 - Systeme.

drfunfrock
31.05.2008, 17:53
Ich finde die Oscat-Libs klasse, zumindestens als Ideengeber. In wichtigen Bereichen wie einer Programmierung für Klemmen ist aber kaum mit einheitlichen Libs zu rechnen.

Aber wie kann man in einem Projekt zwei verschiedene SPS-Lieferanten auswählen? Das ist doch wirklich dämlich! Jeder weiss doch, dass die Interoperabilität zwischen zwei SPS-Lieferanten ziemlich eingeschränkt ist.

gravieren
31.05.2008, 18:03
Aber wie kann man in einem Projekt zwei verschiedene SPS-Lieferanten auswählen?

Lade dir die Lib z.b. für Step 7 --> Step 7 Programme schreiben.
Lade dir die Lib z.b. für CoDeSys --> Programme für Wago, Beckhoff ...

Du kannst dir aber auch die Quell-Codes (ST) rausziehen und in dein Programm kopieren.



Das ist doch wirklich dämlich! Jeder weiss doch, dass die Interoperabilität zwischen zwei SPS-Lieferanten ziemlich eingeschränkt ist.

Was meinst du damit.

Oberchefe
02.06.2008, 20:26
Leider gibt es nur wenige CoDeSys-eigenen Bibliotheken.
Die, die es gibt sind Quelltext-offen.

sollte wohl eher heißen

Die, die es gibt sind nicht Quelltext-offen.

gravieren
12.06.2008, 17:56
Hi



sollte wohl eher heißen

Code:
Die, die es gibt sind nicht Quelltext-offen.


Ich habe die "Orginal" - CoDeSys-Libs gemeint.
(Die bei der Umgebung von CoDeSys --> NICHT die von den Herstellern dabei sind )

Also den PID ...

Die sind Quelltext-offen.

mv08
03.07.2013, 13:59
Wo finde ich denn die Funktion LREAL_TO_FMTRSTRING. Denn mein TwinCat kennt nicht LREAL_TO_FMTRSTRING

mv08
03.07.2013, 14:01
Wo finde ich denn die Funktion LREAL_TO_FMTRSTRING. Denn mein TwinCat kennt nicht LREAL_TO_FMTRSTRING

Gerade selber gefunden: http://infosys.beckhoff.com/index.php?content=../content/1031/tcplclibutilities/html/tcplclibutilities_lreal_to_fmtstr.htm&id=
Klappt wunderbar damit.