Step 7 Werte in AWL vergleichen

Japapa10

Level-1
Beiträge
4
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Freunde,

bin neu hier und suche im Zuge meiner Technikerarbeit Hilfe beim Programmieren.

Ich möchte Werte bzw. 2 Sequenzen miteinander vergleichen.
Der eine Wert muss immer um 2 größer sein als der Andere und die Werte laufen von 0001-2999 (also z.B. 2000 und 1998 ist ok).
Beide sind jeweils in einem DB in einem Array (Char) gesichert.

SCL darf leider nicht verwendet werden, weshlab ich in AWL programmieren muss, aber dort blutiger Anfänger bin.

Macht es Sinn die Werte einzeln zu laden und in ein INT umzuwandeln und dann zu vergleichen?

Bsp:
L 4
T LB 1
L #lfd_Nr_L_Zeichen1
T #Temp_lfd_Nr_L[1]
L #lfd_Nr_L_Zeichen2
T #Temp_lfd_Nr_L[2]
L #lfd_Nr_L_Zeichen3
T #Temp_lfd_Nr_L[3]
L #lfd_Nr_L_Zeichen4
T #Temp_lfd_Nr_L[4]

CALL "STRNG_I"
S :=#Temp_lfd_Nr_L
RET_VAL:=#Temp_lfd_Nr_L_int
SET
= #HM_1

Wenn ich den selben Code für die rechte Zahlensequenz verwende, passiert leider nichts (ich vermute wegen LB 1, bin mir aber nicht sicher).

Kann mir jemand helfen?

Vielen Dank vorab!
 
Falls #Temp_lfd_Nr_L ein STRING in TEMP ist: Du mußt vor Verwendung des STRINGs (z.B. mit "STRNG_I") beide Bytes im String-Header initialisieren, also vermutlich auch das LB0

Code:
[COLOR="#0000FF"]      LAR1  P##Temp_lfd_Nr_L
      L     4
      T     LB [AR1, P#0.0]
      T     LB [AR1, P#1.0][/COLOR]
      L     #lfd_Nr_L_Zeichen1
      T     #Temp_lfd_Nr_L[1]
      L     #lfd_Nr_L_Zeichen2
      T     #Temp_lfd_Nr_L[2]
      L     #lfd_Nr_L_Zeichen3
      T     #Temp_lfd_Nr_L[3]
      L     #lfd_Nr_L_Zeichen4
      T     #Temp_lfd_Nr_L[4]

 CALL  "STRNG_I"
       S      :=#Temp_lfd_Nr_L
       RET_VAL:=#Temp_lfd_Nr_L_int
      SET   
      =     #HM_1

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also den Sinn der Zuweisung auf das LB1 erschliesst sich mir nicht - ich vermute aber, dass du damit eigentlich den String-Header beschreiben möchtest. Nun ist aber Temp_lfd_Nr_L gar kein String sondern ein Array - da funktioniert das dann sowieso nicht.
Du müßtest also Folgendes machen :
- dein Array_of_Char in einen String umwandeln
- deinen String in einen Integer umwandeln
- das jetzt mit deiner Vorgabe vergleichen
Du könntest aber auch dein Array_of_Char (da es ja nur 4 Elemente sind) direkt zu einer Zahl machen ... (Zeichen_T * 1000 + Zeichen_H * 100 + ...) ... bedenke aber, dass ein Char nicht die Zahl selbst sondern deren ASCII-Code enthält ....

Gruß
Larry
 
Danke für euere Antworten!

Habe das Umwandeln soweit zum Laufen bekommen!
Versuche mich jetzt mal an der Logik (Vergleich beim Sequenzumsprung von 2999 auf 0001).

Ein schönes Wochenende vorab ;-)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... (Zeichen_T * 1000 + Zeichen_H * 100 + ...) ...
bedenke aber, dass ein Char nicht die Zahl selbst sondern deren ASCII-Code enthält ....

Code:
ASCII    hex    dec
' '       20     32
'0'       30     48
...
'9'       39     57

Wenn der String ausschliesslich Ziffern ('0' ... '9') enthält: von jedem Zeichen 48 sutrahieren.
Wenn der String ausser Ziffern noch blanks (Leerzeichen) an den Stellen enthält, wo vorlaufende Nullen unterdrückt wurden: jedes Zeichen mit 15 verodern.
Achtung: wenn String weitere Zeichen (Vorzeichen, Trennzeichen, Komma, u.s.w.) enthält, geht es nicht so einfach!

Also:
Zahl = (Zeichen_T - 48 ) * 1000 + (Zeichen_H - 48 ) * 100 + (Zeichen_Z - 48 ) * 10 + (Zeichen_E - 48 )
bzw.
Zahl = (Zeichen_T OR 15) * 1000 + (Zeichen_H OR 15) * 100 + (Zeichen_Z OR 15) * 10 + (Zeichen_E OR 15)

oder in Schleife:
Code:
Zahl = 0
[FONT=courier new]For x = 1 To 4 By 1 Do
    Zahl = Zahl * 10 + (Zeichen[x] OR 15)
    End_For

[/FONT]
Das klingt als ob die Anweisung MOD hilfreich wäre.

... sogar bei der Umwandlung ASCII in DINT in AWL:

Code:
L    dw4ASCII          (* DoppelWort, das die 4 ASCII-Zeichen enthält *)
L    DW#16#0F0F0F0F
UD 
L    L#65536
/D 
T    dintTemp
TAK 
L    L#65536
MOD 
L    L#256
MOD 
T    dintErgebnis
TAK 
L    L#256
/D 
L    L#10
*D 
L    dintErgebnis
+D 
T    dintErgebnis
L    dintTemp
L    L#256
MOD 
L    L#100
*D 
L    dintErgebnis
+D 
T    dintErgebnis
L    dintTemp
L    L#256
/D 
L    L#1000
*D 
L    dintErgebnis
+D 
T    dintErgebnis
Häwenaissuiikend! Gruss, Heinileini
 
Zuletzt bearbeitet:
Wenn der String ausschliesslich Ziffern ('0' ... '9') enthält: von jedem Zeichen 48 sutrahieren.

Wenn wirklich in jeder der vier Stellen immer eine gültige Ziffer steht und er nur die Werte auf größer/kleiner/gleich vergleichen möchte, dann muss daran gar nicht herumgerechnet werden.
Er muss nur die vier Zeichen der zu vergleichenden Zeichenketten in passender Reihenfolge in zwei DInt-Variablen kopieren, und diese dann mit >D, <D und ==D vergleichen.
 
Wenn wirklich in jeder der vier Stellen immer eine gültige Ziffer steht und er nur die Werte auf größer/kleiner/gleich vergleichen möchte, dann muss daran gar nicht herumgerechnet werden.

Stimmt! Aber, wenn ...
Der eine Wert muss immer um 2 größer sein als der Andere und die Werte laufen von 0001-2999 (also z.B. 2000 und 1998 ist ok).

... dann eben nicht bzw. doch oder so ... ;o(
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Das Umwandeln der 4 CHAR (ASCII-Ziffern) in INT würde ich anstatt der Ziffernzerlegung und Multiplikationen so machen:
Code:
//Umwandeln 4 ASCII-Ziffern '0000'..'9999' nach INT 0..9999
//Falls Zeichen <> Ziffern '0'..'9' enthalten sind, dann kann die CPU bei BTD in STOP gehen!
      L     #dw4ASCII           //DoppelWort, das die 4 ASCII-Ziffern enthält
      UD    DW#16#F0F0F0F       //ASCII->BCD mit ZwischenTetraden
      PUSH
      SRD   4
      OD
      UD    DW#16#FF00FF
      SLW   8
      SRD   8
      BTD                       //BCD->DINT  (OB121 sollte vorhanden sein)
      T     #iWert              //INT 0..9999

und den Vergleich der zwei Werte 1..2999, ob Wert2 2 Schritte weiter als Wert1 ist:
Code:
//Vergleich Wert2 ist 2 Schritte weiter als Wert1?
      L     #iWert1             //1..2999
      +     1                   //2..3000
      L     2999
      MOD                       //2..2998  2999->0  3000->1
      +     1                   //3..2999  1        2
      L     #iWert2
      ==I
      =     #OK

Harald
 
Wo kann man denn hier "gefällt mir" anklicken?
Code:
      SLW   8
      SRD   8

... hat noch ein extra "gefällt mir" verdient.

Zum (durch den TE) nachgeschobenen "Vergleich beim Sequenzumsprung von 2999 auf 0001" wissen wir eigentlich zu wenig, was genau ablaufen soll.
Wenn man die Hintergründe nicht kennt, die zu der (vermeintlichen) Aufgabenstellung führen, werde ich ganz skeptisch.
Vermutlich hast Du Recht, Harald. Und meine Bedenken sind nur überzogen.
Mir gefällt gar nicht, wenn sich die Aufgabenstellung erst so nach und nach herauskristallisiert.
Manchmal ergibt sich dann erst kurz vor Schluss, dass ein ganz anderer Ansatz der geeignete wäre.
Gruss, Heinileini
 
Zuviel Werbung?
-> Hier kostenlos registrieren
und den Vergleich der zwei Werte 1..2999, ob Wert2 2 Schritte weiter als Wert1 ist:
Code:
//Vergleich Wert2 ist 2 Schritte weiter als Wert1?
      L     #iWert1             //1..2999
      +     1                   //2..3000
      L     2999
      MOD                       //2..2998  2999->0  3000->1
      +     1                   //3..2999  1        2
      L     #iWert2
      ==I
      =     #OK

Genau das habe ich in dieser Form gesucht! Vielen Dank und Entschuldigung, wenn ich mich vorher undeutlich ausgedrückt habe...;)

Schöne Grüße
 
Zurück
Oben