Zustandsbits in Zustands-Integer

Zuviel Werbung?
-> Hier kostenlos registrieren
Da das Ergebnis einer Potenz vom Datentyp REAL ist, muss der Programmcode noch etwas geändert werden:

Code:
FUNCTION FC202 : INT
VAR_INPUT
m_word : INT; // zu prüfendes Wort
END_VAR
VAR_TEMP
i_temp : INT; // temporäre Variable
END_VAR
IF m_word = 0 THEN
i_temp := 0; 
ELSIF m_word = -32768 THEN
// Anweisungsteil_ELSIF
i_temp := 16;
ELSE
[B][COLOR=green]i_temp := REAL_TO_INT (2**(m_word - 1)) ;[/COLOR][/B]
END_IF;
FC202 := i_temp;
END_FUNCTION

Gruß Kai
 
Opps ...

Danke Kai, da habe ich mich jetzt direkt vertan. Natürlich meinte ich die **-Geschichte für die Potenz-Bildung ...

Übrigens, du brauchst m.E. keine Typ-Konvertierung machen ...
 
@Kai:
Stimmt - ** liefert als Ergebnis ein REAL zurück.

@Mangokind:
Die dargestellte Funktion entspricht im Grunde dem AWL-Befehl SLW (oder besser vielleicht SLD). Meinst du nicht, dass sich deine Aufgabenstellung durch einfaches Linksschieben eines Startwertes auch schon machen läßt ? Also etwa so :
Code:
L 1
L #Arbeitsstation
SLD
T #Statusmeldung
Gruß
LL
 
@Mangokind:
Die dargestellte Funktion entspricht im Grunde dem AWL-Befehl SLW (oder besser vielleicht SLD). Meinst du nicht, dass sich deine Aufgabenstellung durch einfaches Linksschieben eines Startwertes auch schon machen läßt ? Also etwa so :
Code:
L 1
L #Arbeitsstation
SLD
T #Statusmeldung
Gruß
LL

mein lieber larry, du sollst nicht am sinn und unsinn eines ansatzes zweifeln! :cool:
 
Eine andere Idee...

ist evtl. das:

Code:
// Erzeuge Datenkopie
      CALL  "BLKMOV"
       SRCBLK :=P#DB50.DBX0.0 BYTE 16
       RET_VAL:=#RET_VAL_SFC20
       DSTBLK :=P#DB50.DBX148.0 BYTE 16
 
// 1. gesetztes Bit ermitteln
      L     1
      T     #Schleife
m01:  NOP   0
      L     DB50.DBD  160
      RRDA  
      T     DB50.DBD  160
      L     DB50.DBD  156
      RRDA  
      T     DB50.DBD  156
      L     DB50.DBD  152
      RRDA  
      T     DB50.DBD  152
      L     DB50.DBD  148
      RRDA  
      T     DB50.DBD  148
      SPP   Fehl                        // Bei gesetztem A1
      L     #Schleife
      INC   1
      T     #Schleife
      L     #Schleife
      L     129
      <>I   
      SPB   m01
      L     0
      T     #Schleife
Fehl: NOP   0
      L     #Schleife
      T     DB59.DBB    6

Hier werden z.Bsp. 16 Byte durchwühlt. Allerdings ist es fraglich ob ein Schleifenkonstrukt wirklich schneller ist als ein Logarithmus..!?
Dieses Stück Programm kann man sicherlich noch schneller machen, indem man den Datenbereich in den lokalen Bereich umkopiert. Hab's halt aus nem rel. alten Proj. rauskopiert :rolleyes:.
 
ist evtl. das:

Code:
// Erzeuge Datenkopie
      CALL  "BLKMOV"
       SRCBLK :=P#DB50.DBX0.0 BYTE 16
       RET_VAL:=#RET_VAL_SFC20
       DSTBLK :=P#DB50.DBX148.0 BYTE 16
 
// 1. gesetztes Bit ermitteln
      L     1
      T     #Schleife
m01:  NOP   0
      L     DB50.DBD  160
      RRDA  
      T     DB50.DBD  160
      L     DB50.DBD  156
      RRDA  
      T     DB50.DBD  156
      L     DB50.DBD  152
      RRDA  
      T     DB50.DBD  152
      L     DB50.DBD  148
      RRDA  
      T     DB50.DBD  148
      SPP   Fehl                        // Bei gesetztem A1
      L     #Schleife
      INC   1
      T     #Schleife
      L     #Schleife
      L     129
      <>I   
      SPB   m01
      L     0
      T     #Schleife
Fehl: NOP   0
      L     #Schleife
      T     DB59.DBB    6

Hier werden z.Bsp. 16 Byte durchwühlt. Allerdings ist es fraglich ob ein Schleifenkonstrukt wirklich schneller ist als ein Logarithmus..!?
Dieses Stück Programm kann man sicherlich noch schneller machen, indem man den Datenbereich in den lokalen Bereich umkopiert. Hab's halt aus nem rel. alten Proj. rauskopiert :rolleyes:.

@StefanK

Ok, über indirekte Adressierung ist der Aufwand aber auch nicht größer.

PS: Muß man den den Logarithmus-Ansatz nicht auch in einer Schleife machen, wenn man alle Einsen eines Wortes als Zahl irgendwohin schreiben will? Ich kann grad noch nicht sehen, daß der Aufwand da wirklich geringer wäre, als einfach durchzuzählen.

PS2: Das gilt auch für den obigen FC202, bei einem gesetzten Bit sehe ich ja den nutzen durchaus. Oder habe ich die Aufgabenstellung nicht mehr richtig in Erinnerung?
 
Zuletzt bearbeitet:
rein mathematisch müsste ich mir nur den exponenten zur basis 2 ausgeben lassen, aber ein kurzer blick ins S7 PDF mit der ausführungszeit für logarithmen hat mich ganz schnell wieder von dieser idee abgebracht

würde den code zwar zu nem 10-zeiler vereinfachen, aber die laufzeit...:rolleyes:

Wenn Du nur den Exponenten zur Basis 2 brauchst, versuchs mal so:
Code:
L #i_temp  // Integerwert
ITR // in Realzahl wandeln
SLD 1 // Vorzeichen rausschieben
SRD 24 // Mantisse rausschieben
T #Exponent // da ist der Exponent zur Basis 2

Ich hab' jetzt aber nicht geguckt, wie lang die Ausführungszeit ist.

Grüße
Gebs
 
Wenn Du nur den Exponenten zur Basis 2 brauchst, versuchs mal so:
Code:
L #i_temp  // Integerwert
ITR // in Realzahl wandeln
SLD 1 // Vorzeichen rausschieben
SRD 24 // Mantisse rausschieben
T #Exponent // da ist der Exponent zur Basis 2
Ich hab' jetzt aber nicht geguckt, wie lang die Ausführungszeit ist.

Grüße
Gebs

coole sache wenns funktioniert... die ausführungszeit laut tabelle ist vernachlässigbar klein (DTR -> 2,7 microsek. auf ner 315) :)

mal sehen, ob ich da nicht morgen n fixen ansatz draus gebacken bekomme...

wenn nur 1 bit gesetzt werden dürfte, wärs mit dem exponenten ja schon getan...

aber bei mehreren sollte man gefundene bits eigentlich per XOW wegmaskieren können und das ganze einfach nochmal machen können

danke an alle!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
coole sache wenns funktioniert...

Also in S5 hat es funktioniert. Aber da war es ja KG. Ich hab' noch mal nachgesehen und
wenn ich mich nicht verguckt hab, unterscheiden sich KG und REAL nur beim BIAS, und das ist
bei natürlichen Zahlen nicht relevant.

Grüße
Gebs
 
aber bei mehreren sollte man gefundene bits eigentlich per XOW wegmaskieren können und das ganze einfach nochmal machen können

Aber mir ist immer noch unklar, was das wirklich bringt (an Vereinfachung und/oder Rechenzeitersparnis). Hängt sicher davon ab, wieviele Bits so im Durchschnitt gesetzt sind. Der resultierende Code würde mich dann mal interessieren.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
mal ein beispiel:

ich habe ein WORD, indem bit 4 und bit 8 gesetzt sind... (beim ersten word also bspw Zustand 5 und 9 der maschine)

also 2^4+2^8=272 als integerwert

wenn man sich den dualen logarithmus davon ausrechnet kommt wie zu erwarten immer der größeren der beiden exponenten raus... also 8,087...
wenn man den teil nach dem komma auswertet, weiß man, ob es mehrere gesetzte bits gibt, der teil vor dem komma gibt (innerhalb des wortes) das höchstwertigste gesetzte bit an.


müsste ich dann nicht, um das nächste gesetzte bit zu finden, eine 1 in den akku laden, diese in einer schleife so oft, wie der gefundene größte exponent war, nach links verschieben (SLW akzeptiert keine variable), dann das ursprungs-WORD XOR mit akku 1 verknüpfen bzw subtrahieren und dann das ganze nochmal machen, solange der Nachkommateil des exponenten nicht 0 ist, es also noch weitere gesetzte bits gibt?

alternativ könnte man den gefundenen größten exponenten natürlich auch auf nen pointer addieren, der auf einen vergleichsinteger zeigt und das bit dann 0 setzen... kann ich gerade nicht abschätzen, was günstiger ist.

---------------------------------

habe mir mal das Real-format angeschaut...

wenn 1 bit gesetzt ist, habe ich also immer eine mantisse von 1

ich müsste demnach nicht den exponenten, sondern die mantisse überprüfen, ob sie glatt 1 ist

aber das problem bleibt doch: wie berechne ich weitere bits, wenn die mantisse ungleich 1 ist?

das höchste gesetzte bit ist immernoch das was im exponenten steht, aber den rest muss ich ja trotzdem gesondert behandeln


mal zurück zum beispiel von vorhin: 2^4+2^8=272

wenn ich jetzt 272 in eine real-zahl wandle, bekomme ich vermutlich 1,0625*2^8 als real-zahl, wenn ich den datentyp richtig verstanden habe

ich müsste doch also 2^8 von den 272 abziehen und dann das ganze nochmal machen, oder? und zwar solange, bis meine mantisse mal 1,0 wäre bzw ich alle gesetzten bits in dem wort gefunden habe

so langsam bekomme ich auch zweifel, ob der ursprüngliche ansatz so schlecht war... denn ich bekomme hier ja wieder die verschachtelte schleife aus post #2, nur dass die innere schleife hier mit den exponenten rumrechnet, statt bitweise zu prüfen

bitte korrigier mich, wenn ich mich irre...

LG


P.S.:

wie sieht eigentlich 0.0 als REAL-Zahl aus?

da man die Vorkommastelle nicht beeinflussen kann, wäre das ja 1,X*2^Y

1,X kann nicht 0 werden, 2^Y kann auch nicht 0 werden... mhhhh


------------------------------------------

habs mal schnell zusammengetippert:

über Exponenten auswerten:

(nur der rot markierte teil hat sich geändert)

Code:
      TAR1  #AR1Merker
      TAR2  #AR2Merker
//IN nach TEMP
      L     #QuellDB                    //IN-Var... DB-Nummer Quelle
      T     #QDB                        //TEMP-Var... DB-Nummer Quelle
      L     #ZielDB                     //IN-Var... DB-Nummer Ziel
      T     #ZDB                        //TEMP-Var... DB-Nummer Ziel
// --- initialisieren ---
//Zaehler/Merker initialisieren
      L     0
      T     #GefundeneZst
//Offset der aeusseren Schleife 0 setzen
      L     0
      T     #OffsetAussen
//Zst-Ints im Ziel-DB 0 setzen
      AUF   DB [#ZDB]
      L     #ZielAnfang                 //IN-Var... Byteposition des ersten Zst-Ints im Ziel-DB
      SLD   3
      LAR1  
      L     #AnzahlInteger
nw1a: T     #SchleifeInnen
      L     0
      T     W [AR1,P#0.0]
      +AR1  P#2.0
      L     #SchleifeInnen
      LOOP  nw1a
 
// --- Pruefschleifen ---
//*** Pruefschleife aussen: testet je 16 bits, ob überhaupt eins davon gesetzt ist ***
      L     #HoechsterZustand           //Anzahl Bits
      SRW   4
      +     1                           //Anzahl Woerter
nw1b: T     #SchleifeAussen
      AUF   DB [#QDB]
      L     #OffsetAussen               //Anzahl gepruefter Bytes
      L     #QuellAnfang
      +I    
      SLD   3
      T     #QPointer                   //Pointer auf aktuell zu testenden Quellbereich
      LAR1  
      L     W [AR1,P#0.0]
      L     0
      ==I   
      SPB   nw1e                        //wenn kein bit true ist, muss man auch nicht schauen, welches true ist
[COLOR=red]//***Innere Schleife***[/COLOR]
[COLOR=red]//hoechstes gesetztes Bit ermitteln[/COLOR]
[COLOR=red]   L     W [AR1,P#0.0]               //das gerade zu pruefende WORD[/COLOR]
[COLOR=red]nw1c: T     #WORDMerker                 //gemerkt (noetig bei mehreren Durchlaeufen)[/COLOR]
[COLOR=red]   DTR                               //als REAL[/COLOR]
[COLOR=red]   T     #REALMerker                 //merken[/COLOR]
[COLOR=red]   SLD                               //Vorzeichen weg[/COLOR]
[COLOR=red]   SRD   24                          //bleibt nur noch der Exponent bzw das hoechste gesetzte bit[/COLOR]
[COLOR=red]   T     #Exponent[/COLOR]
[COLOR=red]//noch weitere Bits gesetzt?[/COLOR]
[COLOR=red]   L     #REALMerker                 //REAL wieder Laden[/COLOR]
[COLOR=red]   SLD   9                           //Vorzeichen und Exponent weg... [/COLOR]
[COLOR=red]   SRD   9                           //bleiben noch 23 Bit Nachkommastelle der Mantisse[/COLOR]
[COLOR=red]   L     0[/COLOR]
[COLOR=red]   ==D                               //wenn Nachkommastellen ==0 wurde das letzte gesetzte Bit gefunden[/COLOR]
[COLOR=red]   =     #MerkerLetzteStelle[/COLOR]
[COLOR=red]//Zielposition im Ziel-DB laden[/COLOR]
[COLOR=red]   AUF   DB [#ZDB][/COLOR]
[COLOR=red]   L     #GefundeneZst               //Anzahl gefundener Zustaende[/COLOR]
[COLOR=red]   SLD                               //*2 um 2 Bytes bzw 1 Int weiterzuspringen[/COLOR]
[COLOR=red]   L     #ZielAnfang                 //IN-Var... Byteposition des ersten Zst-Ints im Ziel-DB[/COLOR]
[COLOR=red]   +D                                //im akku 1 steht die Byte-Nummer des Ints, in das der Zustand gespeichert wird[/COLOR]
[COLOR=red]   SLD   3[/COLOR]
[COLOR=red]   LAR1  [/COLOR]
[COLOR=red]//gefundenen Zustand abspeichern[/COLOR]
[COLOR=red]   L     #OffsetAussen               //Anzahl durchsuchter Bytes[/COLOR]
[COLOR=red]   SLW   3                           //Anzahl durchsuchter Bits[/COLOR]
[COLOR=red]   L     #Exponent                   //Position innerhalb des aktuell durchsuchten Wortes[/COLOR]
[COLOR=red]   +I    [/COLOR]
[COLOR=red]   +     1                           //Nummer des dem Bit zugewiesenen Zustands[/COLOR]
[COLOR=red]   T     W [AR1,P#0.0][/COLOR]
[COLOR=red]//Zaehler erhoehen[/COLOR]
[COLOR=red]   L     #GefundeneZst[/COLOR]
[COLOR=red]   +     1[/COLOR]
[COLOR=red]   T     #GefundeneZst[/COLOR]
[COLOR=red]//Abbruchbedingung: speicherplatz fuer Zustandsnummern ist voll[/COLOR]
[COLOR=red]   L     #GefundeneZst[/COLOR]
[COLOR=red]   L     #AnzahlInteger              //IN-Var... Vorgabe der maximal gleichzeitig gesetzten Zst bzw die Anzahl Speicherplaetze[/COLOR]
[COLOR=red]   ==I   [/COLOR]
[COLOR=red]   BEB   [/COLOR]
[COLOR=red]// ggf. das gefundene Bit vom zu pruefenden WORD abziehen und die ganze Show nochmal[/COLOR]
[COLOR=red]   SET   [/COLOR]
[COLOR=red]   U     #MerkerLetzteStelle[/COLOR]
[COLOR=red]   SPB   nw1e                        //Innere Schleife verlassen[/COLOR]
[COLOR=red]//wenns noch ein weiteres gesetztes bit gibt:[/COLOR]
[COLOR=red]   SET                               //VKE auf 1[/COLOR]
[COLOR=red]   L     P##WORDMerker[/COLOR]
[COLOR=red]   L     #Exponent[/COLOR]
[COLOR=red]   +D    [/COLOR]
[COLOR=red]   LAR1  [/COLOR]
[COLOR=red]   R      [AR1,P#0.0]                //Das gefundene Bit wird zurueckgesetzt[/COLOR]
[COLOR=red]   L     #WORDMerker[/COLOR]
[COLOR=red]   SPA   nw1c                        //und nochn Durchlauf der inneren Schleife[/COLOR]
[COLOR=red]//Ende innere Schleife[/COLOR]
 
//Ende aeussere Schleife
nw1e: L     #OffsetAussen
      +     2
      T     #OffsetAussen               //Anzahl durchsuchter Bytes um 2 erhoehen
      L     #SchleifeAussen
      LOOP  nw1b
      LAR1  #AR1Merker
      LAR2  #AR2Merker
 
Zuletzt bearbeitet:
Zum vergleich aus Post #2: Loopschleife Bitweise auswerten:

Code:
      TAR1  #AR1Merker
      TAR2  #AR2Merker
 
//IN nach TEMP
      L     #QuellDB                    //IN-Var... DB-Nummer Quelle
      T     #QDB                        //TEMP-Var... DB-Nummer Quelle
      L     #ZielDB                     //IN-Var... DB-Nummer Ziel
      T     #ZDB                        //TEMP-Var... DB-Nummer Ziel
// --- initialisieren ---
//Zaehler/Merker initialisieren
      L     0
      T     #GefundeneZst
//Offset der aeusseren Schleife 0 setzen
      L     0
      T     #OffsetAussen
//Zst-Ints im Ziel-DB 0 setzen
      AUF   DB [#ZDB]
      L     #ZielAnfang                 //IN-Var... Byteposition des ersten Zst-Ints im Ziel-DB
      SLD   3
      LAR1  
      L     #AnzahlInteger
nw1a: T     #SchleifeInnen
      L     0
      T     W [AR1,P#0.0]
      +AR1  P#2.0
      L     #SchleifeInnen
      LOOP  nw1a
 
// --- Pruefschleifen ---
//*** Pruefschleife aussen: testet je 16 bits, ob überhaupt eins davon gesetzt ist ***
      L     #HoechsterZustand           //Anzahl Bits
      SRW   4
      +     1                           //Anzahl Woerter
nw1b: T     #SchleifeAussen
      AUF   DB [#QDB]
      L     #OffsetAussen               //Anzahl gepruefter Bytes
      L     #QuellAnfang
      +I    
      SLD   3
      T     #QPointer                   //Pointer auf aktuell zu testenden Quellbereich
      LAR1  
      L     W [AR1,P#0.0]
      L     0
      ==I   
      SPB   nw1e                        //wenn kein bit true ist, muss man auch nicht schauen, welches true ist
[COLOR=red]//***Innere Schleife***[/COLOR]
[COLOR=red]L     16[/COLOR]
[COLOR=red]nw1c: T     #SchleifeInnen[/COLOR]
[COLOR=red]AUF   DB [#QDB][/COLOR]
[COLOR=red]L     #QPointer[/COLOR]
[COLOR=red]L     #SchleifeInnen[/COLOR]
[COLOR=red]+D    [/COLOR]
[COLOR=red]+     -1                          //weil Bits von 0..15, aber SchleifeInnen von 1..16[/COLOR]
[COLOR=red]LAR1  [/COLOR]
[COLOR=red]SET   [/COLOR]
[COLOR=red]U      [AR1,P#0.0][/COLOR]
[COLOR=red]SPBN  nw1d[/COLOR]
[COLOR=red]//wenn das Bit, auf das Bitpointer gerade zeigt, gesetzt ist[/COLOR]
[COLOR=red]//Zielposition im Ziel-DB laden[/COLOR]
[COLOR=red]AUF   DB [#ZDB][/COLOR]
[COLOR=red]L     #GefundeneZst               //Anzahl gefundener Zustaende[/COLOR]
[COLOR=red]SLD                               //*2 um 2 Bytes bzw 1 Int weiterzuspringen[/COLOR]
[COLOR=red]L     #ZielAnfang                 //IN-Var... Byteposition des ersten Zst-Ints im Ziel-DB[/COLOR]
[COLOR=red]+D                                //im akku 1 steht die Byte-Nummer des Ints, in das der Zustand gespeichert wird[/COLOR]
[COLOR=red]SLD   3[/COLOR]
[COLOR=red]LAR1  [/COLOR]
[COLOR=red]//gefundenen Zustand abspeichern[/COLOR]
[COLOR=red]L     #OffsetAussen               //Anzahl durchsuchter Bytes[/COLOR]
[COLOR=red]SLW   3                           //Anzahl durchsuchter Bits[/COLOR]
[COLOR=red]L     #SchleifeInnen              //Position innerhalb des aktuell durchsuchten Wortes[/COLOR]
[COLOR=red]+I                                //Nummer des dem Bit zugewiesenen Zustands[/COLOR]
[COLOR=red]T     W [AR1,P#0.0][/COLOR]
[COLOR=red]//Zaehler erhoehen[/COLOR]
[COLOR=red]L     #GefundeneZst[/COLOR]
[COLOR=red]+     1[/COLOR]
[COLOR=red]T     #GefundeneZst[/COLOR]
[COLOR=red]//Abbruchbedingung: speicherplatz fuer Zustandsnummern ist voll[/COLOR]
[COLOR=red]L     #GefundeneZst[/COLOR]
[COLOR=red]L     #AnzahlInteger              //IN-Var... Vorgabe der maximal gleichzeitig gesetzten Zst bzw die Anzahl Speicherplaetze[/COLOR]
[COLOR=red]==I   [/COLOR]
[COLOR=red]BEB   [/COLOR]
[COLOR=red]//Ende innere Schleife[/COLOR]
[COLOR=red]nw1d: L     #SchleifeInnen[/COLOR]
[COLOR=red]LOOP  nw1c[/COLOR]
//Ende aeussere Schleife
nw1e: L     #OffsetAussen
      +     2
      T     #OffsetAussen               //Anzahl durchsuchter Bytes um 2 erhoehen
      L     #SchleifeAussen
      LOOP  nw1b
      LAR1  #AR1Merker
      LAR2  #AR2Merker

bin ja mal gespannt, was die SPS Zykluszeit dann dazu sagt...


------------------------------------------------------------------------------------------


gleich noch eine frage:

wie bildet man am schlausten eine eindeutige Prüfsumme über erstmal unbegrenzt viele wörter, wenn nur Wertänderung interessiert?




-------------------------------------------------------------------------------------------

@Kai:
Stimmt - ** liefert als Ergebnis ein REAL zurück.

@Mangokind:
Die dargestellte Funktion entspricht im Grunde dem AWL-Befehl SLW (oder besser vielleicht SLD). Meinst du nicht, dass sich deine Aufgabenstellung durch einfaches Linksschieben eines Startwertes auch schon machen läßt ? Also etwa so :
Code:
L 1
L #Arbeitsstation
SLD
T #Statusmeldung
Gruß
LL

war meine allererste idee, ist aber noch langsamer als bitweise prüfen, weil WORD-vergleiche deutlich langsamer sind als bit-vergleiche und sich abgesehen davon nicht viel ändert
 
Zuletzt bearbeitet:
Zurück
Oben