Probleme mit der REAL_TO_INT Funktion

Superfly

Level-1
Beiträge
11
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
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!!
 
Hallo,

wie wäre es anstelle von "REAL_TO_INT" mit "REAL_TO_STRING"?
Code:
LD	4.3
REAL_TO_STRING
ST	HM_STRING

Viele Grüße
MTec
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... 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
 
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?
 
Wie kann man dhier am besten ein Zeichen einfügen?

Das könnte beispielsweise so aussehen:
Code:
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
 
Zuviel Werbung?
-> Hier kostenlos registrieren
...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:
 
Superfly schrieb:
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:
Code:
LD	4.3
ADD	0.1
ST	TestReal
REAL_TO_STRING
ST	TestString   (*--> TestString = '4.4'*)

Viele Grüße
MTec
 
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
Code:
 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??
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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?
Code:
LD	RealDemo
ADD	1.0
ST	RealDemo

LD	RealDemo
DIV	10.0
REAL_TO_STRING
ST	StringDemo
 
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.
 
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.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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
 
@Scrat
sErgebnis := LREAL_TO_FMTRSTRING(rMesswert, 4, TRUE);
Schön, welches System hat den diese Funktion ?


Ich verwende die 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'
 
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
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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

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.
 
Was ist eigentlich der Grund, dass plötzlich zwischen Technologien dh. hier zwischen zwei SPS-Anbietern so wilkührlich gewechselt wird?
 
@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.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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.
 
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.
 
Zurück
Oben