Ich meine damit sowas wie hier: Link
Wie arbeitet man damit richtig? Wo soll es benutzt werden?
Ist es immer nützlich? Arbeitet das Programm schneller damit?
Auf Frage von ioRawr, versuche ich mal den Code zu erklären.
Es ist definitiv nichts für PAWN Anfänger bzw allg. Anfänger im Coding Bereich.
Übrigens, in dem Code fehlt eine Zeile. "return model" muss noch eingefügt werden,sonst bringt die Funktion nichts.
stock GetVehicleSeatCount(model)
{
static const
scMaxPassengers[] =
{
0x10331113, 0x11311131, 0x11331313, 0x80133301, 0x1381F110, 0x10311103, 0x10001F10, 0x11113311, 0x13113311,
0x31101100, 0x30001301, 0x11031311, 0x11111331, 0x10013111, 0x01131100, 0x11111110, 0x11100031, 0x11130221,
0x33113311, 0x11111101, 0x33101133, 0x101001F0, 0x03133111, 0xFF11113F, 0x13330111, 0xFF131111, 0x0000FF3F
};
if (400 <= model <= 611)
{
model -= 400;
model = (scMaxPassengers[model >>> 3] >>> ((model & 7) << 2)) & 0xF;
if (model == 15)
{
return -1;
}
return model; // <---
}
else
{
return -1;
}
}
Erstmal die Vorbereitung.Was haben wir eigentlich?
Wir haben 611 - 400 Fahrzeuge.Sind also 211 Fahrzeuge, für die wir Werte speichern müssen.
Es gibt kein Fahrzeug,dass mehr als 8 Sitzplätze hat ( Bus , 8 + Fahrer ). Damit wir die Zahl 8 in Binär darstellen können,
müssen wir 4 bits verwenden.Denn 8 = 0b1000 . Die höchste Zahl die wir daher darstellen könnte wäre theoretisch 15 in diesem Fall.
Ist aber sowieso nicht möglich,denn sonst hätten wir keine 8 als höchsten Wert für Sitzplätze genommen.
Y_Less verwendet aber die 15 als Spezialfall,bedeutet, dass Fahrzeug bietet überhaupt keine Sitzmöglichkeit ( Weder Fahrer,noch
Beifahrer ). Dazu später mehr.
Bisher haben wir also herrausgefunden,dass wir eigentlich nur 4 bits benötigen pro Fahrzeug und das 211 mal. Macht Insgesamt 844 bits,
um alle Informationen darzustellen.
Da eine Variable ( Cell ) in PAWN 4 Byte hat ( 32 bits ) , können wir pro Variable also 8 ( 32 bits / 4 bits ) Sitzplätzwerte verwalten.
Daraus resultiert,wir haben 8 Blöcke mit jeweils 4 bits pro Variable. Ich nenne diese einfach mal 4 bit-Block im weiteren Verlauf.
Wie wir sehen,Y_Less hat 27 Variablen ( Code basiert allerdings auf einen Post von RyDeR` ) bzw ein Array mit einer
Größe von 27.
Genau genommen ist 211 / 8 = 26,375 . Wir können aber keine 0,375 Variablen erstellen, müssen daher aufrunden. Daher auch 27. Kann man
auch überprüfen durch 26 * 32 bit , sind nur 832 bits.Wir vorher errechnet,wir brauchen aber 844 bits.
Im ersten Schritt müssen wir herrausfinden, in welcher Variablen ( genau genommen, welcher Index ) der Wert für unser Fahrzeug
steckt.
Das geschiet hier:
model -= 400;
model >>> 3
Da die Fahrzeuge erst bei 400, verschieben wir den Anfang zuerst. Wir verschieben alle ModelIDs um 400 nach unten.
Sonst wären die ersten 400 Werte nutzlos ( 0 - 399 ) , da wir für diese keine Werte benötigen.Es gibt nämlich keine Fahrzeuge
mit diesen ModelIDs.
Gehen wir eine Zeile weiter ( model >>> 3 ).
Ist in diesem Fall nichts Anderes als die Berechnung model / 8. Die 8 kommt von den 8 Sitzplatzwerten pro Variable.
Angenommen für die modelid 411.
411 -= 400;
11 >>> 3 = 1
Gut,wir wissen, dass der Wert für ModelID 411 in Index 1 steckt.
Zitat
400 - 407 ( 0 )
408 - 415 ( 1 )
416 = 423 ( 2 )
424 = 431 ( 3 )
...
scMaxPassengers[1] = 0x11311131 = 0b00010001001100010001000100110001 = 0001 0001 0011 0001 0001 0001 0011 0001
Die Farben sind nur zur Verdeutlichung.Ich habe auch einfach mal den Block Fett markiert,den wir später suchen.
Als nächstes müssen wir herrausfinden, in welchem der 4 bit-Blöcke der Wert steckt, den wir suchen.Das passiert hier:
((model & 7) // model & 0b111
In unserem Fall würde es so aussehen:
(( 11 & 7 ) // (( 0b1011 & 0b0111 )
Das Ergebnis daraus ist 3 ( 0b1011 & 0b0111 ). Man hätte an dieser Stelle auch den Rest der Rechnung 11 durch 8 nehmen können.Ergibt ebenfalls
3 und steht für "Wieviele 4 bit-Blöcke müssen wir verschieben,um den gesuchten an vorderster Position zu haben".
In PAWN wäre es übrigens 11 % 8 ( = 3 ).
Wir haben jetzt also den 4 bit-Block gefunden,den wir benötigen.Er ist in der Variable bei Index 1 und dort der vierte 4 bit-Block.
Um an den vierten 4 bit-Block zu kommen,müssen wir den 4 bit-Block 3 Blöcke nach vorne schieben, bzw nach Rechts ( >> ).Das nennt sich Bit-Shiften.
Denn wir beginnen hier bei den Blöcken bei 0 zu zählen.Der 1 4 bit-Block wird nämlich nicht ( also 0 mal ) geshiftet, ist nämlich schon an Vorderster Stelle.
Der 2 4 bit-Block muss um 1 geshiftet werden,damit er an vorderster stelle steht.
Der 3 " " " 2 geshiftet ","
usw usf
Jetzt sind wir bei folgendem Teil. Denn wir müssen zuerst Klammern berechnen.
((model & 7) << 2))
Wir wissen ja, dass wir es um 3 4 bit-Blöcke verschieben müssen,damit der Gesuchte 4 bit-Block am Anfang steht. Da ein 4 bit-Block nun mal aus 4 Bits besteht,müssen wir alles um
3 * 4 Bits verschieben. Das * 4 ist in diesem Fall << 2 , ist identisch .( << 1 wäre * 2 )
Das würde Binäir so aussehen:
Ausgang: 0001 0001 0011 0001 -> 0001 <- 0001 0011 0001
Ergebnis: 0001 0011 0001 0001 0001 0011 0001 -> 0001 <- // Achtung , >> ist nicht >>> ! Macht in diesem Fall aber keinen Unterschied
Jetzt haben wir den 4 bit-Block den wir benötigen an die vordersten 4 bits der Variablen verschoben. Damit wir auch nur diesen 4 bits bekommen,
müssen wir jetzt & 0b111 machen.Dadurch fallen alle bits weg, die wir nicht benötigen.
Für unseren Fall:
0b0001 & 0b1111 = 0b0001 = 1.
Damit wissen wir jetzt entgültig, dass wir 1 Sitzplatz für Fahrzeug 411 haben,neben dem Fahrersitz. Ein Spezialfall ist 15. Hätten wir jetzt also 15 als Lösung bekommen, wüssten wir, dass es eigentlich gar keine Sitzmöglichkeit für diese ModelID gibt. Es ist ein Sonderfall. 15 ist auch gleichzeitig der höchste Wert den wir mit 4 bits darstellen können ( Vorzeichenfrei ) .
Man könnte auch anstatt die 15 eine eine Andere Zahl nehmen. Es wäre irgendeine Zahl zwischen 9 und 15 möglich,da wir ja wissen,dass kein Fahrzeug einen gültigen Wert über 8 hat.
Was haben wir denn jetzt eigentlich davon ? Wir nutzen wenig Speicher, oder für einige Experten ... die AMX wird nicht so groß ( Was sowieso noch nie ein gute Kriterium war ).
Ergebnis:
Die oben gezeigte Variante verbraucht nur 27 * 4 byte , macht also 107 byte ( Technisch werden nur 211 ( Fahrzeuge ) * 4 ( bits ) 844 bits je benutzt).
Würden wir einen Wert pro Variable benutzen, dann hätten 211 byte = 844 byte.
Macht also 107 byte vs 844 byte. Um es mal in Prozent auszudrücken. Die oben gezeigte Variante belegt nur 12.6% von dem Speicher, den die normale Methode verbrauchen würde.Oder auch anders, die normale Methode ist um 788% Größer was den Speicherbedarf betrifft.
Puh... so viel geschrieben, dachte das wird kürzer. Vorraussetzung dafür,dass man es versteht, sind Grundzüge des Binärsystems ( & ; << ; >> ). Sonst wird es mit dem verstehen sicherlich nicht auf anhieb klappen. Ich hoffe ich habe da jetzt nicht totalen Blödsinn geschrieben, so viele 0 und 1 ...
//Edit:
Im übrigen verwende ich das ab und zu.Hier mal ein Beispiel, wie man Waffe + Munition in 1 Variable speichern kann.
stock Class_CompressWeaponInfo(weaponid,ammo) {
new
info;
info = ( ammo << 7 ) | weaponid;
return info;
}