REAL Zahl in ein festes Format

xenon185

Level-1
Beiträge
20
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Zusammen,
ich brauche Hilfe bei einer Zahl Anpassung. Es liegt ein Wert im Format REAL vor den ich in ein definierte Länge formatieren muss, für eine Übertragung im späteren Verlauf.

z.B.:
IST SOLL
1.578 001.57
33.1 033.10

Ich probiere gerade einige Lösungen, die Wuchern bei mir aber derart aus. Vielleicht hat jemand einen gute idee.
Grüße xenon185
 
Hallo,
ich würde die Variable zunächst mit 100 multiplizieren, dann in einen DINT wandeln, nun zu einem String wandeln / konvertieren und bei diesem dann vorne die noch benötigten Nullen davor setzen und anschließend an der 2. Stelle von hinten noch ein Komma einschieben ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
In der oscat lib gibts den Befehl RND()

dabei wird aber nicht abgeschnitten, sondern wie der Name sagt, gerundet.

Die Funktion RND rundet den Eingangswert IN auf N Stellen. Folgt der letzten
Stelle eine Stelle größer 5 wird die letzte Stelle aufgerundet. RND
nutzt intern die Standard Funktion TRUNC() welche den Eingangswert in
einen INTEGER vom Typ DINT wandelt. Hierbei kann es zu einem Überlauf
kommen weil DINT maximal +/- 2.14 * 10^9 speichern kann. Der Wertebereich
von RND ist deshalb auf +/- 2.14 * 10^9 begrenzt. Siehe hierzu auch
die Funktion ROUND welche den Eingangswert auf N Nachkommastellen
rundet.
Beispiel: RND(355.55, 2) = 360
RND(3.555, 2) = 3.6
ROUND(3.555, 2) = 3.56

EDIT: Geht wohl doch nicht so einfach, da die Anzahl der Ziffern bei deiner Aufgabe variabel sind.
 
Zuletzt bearbeitet:
ich habe mir eure Vorschläge mal zugemüte gezogen und habe mich dafür entschieden, die Zahl mit ROUND auf zwei Stellen zu runden und dann eine Abfrage der Zahl zwischen den Zehnerstritten zu machen.
0-10 ---> Bool x1 -- '00'
10-100 ---> Bool x2 -- '0'
100-xxx ---> Bool x3 -- ''

mit den ergebnis dann einfach die Zahl mit '00' oder '0' aufzufüllen als String.

Ich brauche nur noch eine Idee wie ich aus den ergebnisse x1-3 eine Abfrage machen kann.
Ich arbeite mit der CFC-Sparche -> Anfänger

Thx
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Diese Lösung "wuchert" auch schon wieder aus...

Gibt es in Deinem Programmiersystem die Funktion LREAL_TO_FMSTR() nicht? Womit programmierst Du welche CPU?

Du könntest einfacher grundsätzlich '00' vorne dranhängen (oder 100000000 zu der DINT addieren) und dann die letzten 5 Zeichen nehmen.
Kann Deine Zahl auch ein Vorzeichen haben?
Die Zahl kann auch "glatt" sein, da mußt Du auch noch 2 Nachkommastellen erzeugen.
Benutze ein Verfahren was nicht so viele IF... oder Vergleiche für bedingte Programmausführungen erfordert, sondern immer funktioniert.

Harald
 
Ok, ich hab das mal in ST zusammengebaut, so auf die Schnelle.
Damit funktioniert es, aber nur für positive Werte, sollen es auch negative sein, muss man da noch eine gesonderte Behandlung einbauen.
Ist aber in ST, nicht in CFC, ich habe das als FB aufgebaut, hier reicht auch ein FC, wenn nötig. Diesen Baustein kann man dann evtl. in CFC verwenden? Das hab ich aber nicht nie probiert.


FB-Variablendeklaration:
Code:
FUNCTION_BLOCK ZAHL_TO_STR
VAR_INPUT
    rWert: REAL;
END_VAR
VAR_OUTPUT
    sWert: STRING(6);
END_VAR
VAR
    diWert, helper_diWert: DINT;
    aByWert: ARRAY[0..5] OF BYTE;
    I: INT;
END_VAR

FB-Code:
Code:
        diWert := REAL_TO_DINT(rWert * 100);


    FOR I := 0 TO 5 DO
        IF I = 2 THEN                                            (*3. Stelle von rechts soll Dezimalzeichen sein*)
            aByWert[5- I] := 46;                                  (*46 = ASCII-Code für '.'  *)
        ELSE
            helper_diWert := diWert MOD 10;                     (*Zahlenwert letzte Stelle ermitteln*)
            aByWert[5- I] := DINT_TO_BYTE(helper_diWert) + 48;     (* 48 addieren macht aus einer Zahl den dazugehörigen ASCII-Code *)
            diWert := diWert / 10;                                (*duch 10 dividieren, um oben in der Schleife den nächsten Zahlenwert zu ermitteln*)
        END_IF;
    END_FOR;


    MEMCPY(ADR(sWert), ADR(aByWert), 6);                        (*Array of Byte mit Char gefüllt in einen String kopieren*)

Wie immer gibt es viele Möglichkeiten, diese hier ist halt so richtig zu Fuß! :ROFLMAO:

PS: Warum haut unsere Forensoftware eigentlich immer die Formatierung halb in den Eimer?

PS2: Ach so, wenn man anders runden will, dann in der ersten Zeile ins andere Wandlung vornehmen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Folgendes sollte auch einfach in CFC übersetzbar sein:
Code:
diTemp1 := REAL_TO_DINT(rEingangswert * 100.0);
diTemp2 := ABS(diTemp1);

sAusgabe := '';
IF diTemp1 <> diTemp2 THEN
  sAusgabe := '-';
END_IF;

sTemp := DINT_TO_STRING(diTemp2 + 100000000);
sAusgabe := CONCAT(sAusgabe, MID(sTemp, 3, 5);
sAusgabe := CONCAT(sAusgabe, '.');
sAusgabe := CONCAT(sAusgabe, RIGHT(sTemp, 2));

Harald
 
Danke Leute,
ich habe jetzt ein wenig gesündigt, bin einfach noch Anfänger.
Hab die Idee mit den addieren aufgenommen ist für mich das einfachste, da ich nur positive Werte erwarte mit einem festen Werte Berreich von 0.00 - 400.00

Zahl: 0.1
addiere: 1000.001
Ergebiss: 1000.101
MID() selektiere ich dann ab der zweiten Stelle sechs ziffern 000.10.
das reicht für mich als ergebiss.
Wenn ich später mehr vom ST verstehe mach ich das in neuen Programm anständig ;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ist mir bei Mittag auch aufgefallen :D

da ich aber das Ergebnis mit 2 nachkommastellen bekomme sollte das das mit dann 0.00001 kein problem mehr darstellen.
Nur wenn ich jetzt die Variable auf LREAL ändere bekomme ich die Fehlermeldung: 'LREAL' wird nicht unterstützt.
Das es immer wieder neu Stolpersteine gibt :/

Software: Codesys
Hardware: WAGO 750-881

hmmm, liegt das an der Hardware, die den Datentyp nicht verarbeiten kann?
 
Du mußt die Umwandlung über DINT machen. Damit die Nachkommastellen nicht verloren gehen, und damit auch x.00 möglich ist, muß vor dem REAL_TO_DINT mit 100.0 multipliziert werden.

Harald
 
Zurück
Oben