Übersetzung Java => PB

Fragen zu allen anderen Programmiersprachen.
Syntacks_Error
Beiträge: 107
Registriert: 08.03.2009 16:08

Übersetzung Java => PB

Beitrag von Syntacks_Error »

Ich quäle mich mit folgender Java-Zeile:

j8 = i6 << 16 | i5 & 0xffff

und bekomme sie in PB nicht hin. Es kommt zwar etwas heraus, aber das Ergebnis stimmt nicht.

i6 und i5 sind Integer (normale PB SmallEndians), die aber garantiert in je 2 Byte passen. Der Sache nach geht es also darum, zwei Werte im Wertebereich eines Words aus zwei Intergern in die Bytes 1 und 2 sowie 3 und 4 einer Integer zu schreiben (Wozu das auch immer gut sein soll).
Macht es einen Unterschied, ob man die Werte erst in BigEndians (also Javaformat) umwandelt? Habe ich auch schon versucht, klappt aber auch nicht, dann kommt nur noch 0 heraus. Umwandeln geht, falls doch erforderlich mit dem Makro.

Code: Alles auswählen

 Macro intEndian
 zahl = i5
 Zahl = ((Zahl&$FF)<<24)+((Zahl&$FF00)<<8)+((Zahl&$FF0000)>>8)+((Zahl>>24)&$FF)
 i5 = zahl
 
zahl = i6
 Zahl = ((Zahl&$FF)<<24)+((Zahl&$FF00)<<8)+((Zahl&$FF0000)>>8)+((Zahl>>24)&$FF)
 i6 = zahl 
EndMacro

i5.i = 143
i6.i = 845
j8.i = i6 << 16 | i5 & $ffff
debug j8.i
Wertet PB den Ausdruck vielleicht anders aus als Java? Was muß ich dann ändern?
Zuletzt geändert von Syntacks_Error am 07.05.2011 22:31, insgesamt 1-mal geändert.
Benutzeravatar
Mok
BotHunter
Beiträge: 1484
Registriert: 26.12.2005 14:14
Computerausstattung: MSI GX780R
Intel Core i5-2410M
Nvidia GT 555M
Windows 7 Home Premium 64 bit
Wohnort:   

Re: Übersetzung Java => PB

Beitrag von Mok »

Syntacks_Error hat geschrieben: j8 = i6 << 16 | i5 & $ffff
$ffff müsste auch eine Variable sein, da das Dollar-Zeichen in Java AFAIK wie ein Buchstabe gewertet wird.
Win 7 Home Premium 64 bit | PureBasic 5.20 - x86 und x86-64 | Firefox [aktuelle stable-Version hier einfügen]
"Jeder macht irgendwann mal Fehler, darum gibt's auch Bleistifte mit Radiergummi." --Carl
Syntacks_Error
Beiträge: 107
Registriert: 08.03.2009 16:08

Re: Übersetzung Java => PB

Beitrag von Syntacks_Error »

Fehler meinerseits, im Java-Code heißt es tatsächlich 0xffff, habe es oben korrigiert, tschulligung.
Benutzeravatar
TomS
Beiträge: 1508
Registriert: 23.12.2005 12:41
Wohnort: München

Re: Übersetzung Java => PB

Beitrag von TomS »

Code: Alles auswählen

i5.i = 143
i6.i = 845
j8.i = i6 << 16 | i5 
Debug j8.i
Debug j8 >> 16
Debug j8  & $FFFF
Nehme ich mal an.
Syntacks_Error
Beiträge: 107
Registriert: 08.03.2009 16:08

Re: Übersetzung Java => PB

Beitrag von Syntacks_Error »

Klappt leider auch nicht. Ich erwarte einen sehr großen Ergebniswert, da die Dinger ja wieder ausgelesen werden und dann wieder den Ursprungswert ergeben müssen, es sollten also alle vier bytes gefüllt sein, nehme ich an.
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Re: Übersetzung Java => PB

Beitrag von Danilo »

TomS hat geschrieben:

Code: Alles auswählen

i5.i = 143
i6.i = 845
j8.i = i6 << 16 | i5 
Debug j8.i
Debug j8 >> 16
Debug j8  & $FFFF
In Java:

Code: Alles auswählen

public class Main {
    public static void main(String[] args) {
        int i5,i6,j8;
        i5 = 143;
        i6 = 845;
        j8 = i6 << 16 | i5 & 0xffff;
        System.out.println(j8);
    }
}
Gleiches Ergebnis bei beiden Version: 55378063
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Syntacks_Error
Beiträge: 107
Registriert: 08.03.2009 16:08

Re: Übersetzung Java => PB

Beitrag von Syntacks_Error »

Ups, stimmt, ich hatte nur auf die letzte Debugausgabe geachtet, aber das ist ja schon die Zurückumwandlung.
Klappt in der Tat, ich erhalte jetzt immerhin im wesentlichen schon halbwegs vernünftige Werte. Gibt aber noch ein Problem: Da gibt es auch den Ausdruck wie

l2 = 312 ; immer ein Wert, der auch in 2 byte paßt
k7 = -3109; immer ein Wert, der auch in 2 Byte passt

l7 = k7 << 16 | l2 & $7fff

also $7fff und nicht $ffff,
Was mache ich denn damit?
Einfach weglassen wie das $ffff geht ja sicherlich nicht.

Das ist wohl die letzte Hürde, ich hoffe also nochmal auf Hilfe.
Benutzeravatar
TomS
Beiträge: 1508
Registriert: 23.12.2005 12:41
Wohnort: München

Re: Übersetzung Java => PB

Beitrag von TomS »

Geht genauso. Musst halt bei der Rückwandlung auch wieder 7fff nehmen.

Code: Alles auswählen

i5.i = 312 
i6.i = -3109
j8.i = i6 << 16 | (i5 & $7FFF) ;Hier die Klammern. Ohne geht's nicht.
Debug j8.i
Debug j8 >> 16
Debug j8  & $7FFF
Der Code musste ergänzt werden.
Hab das beim obigen Code weggelassen, da unnötig.
Aber in dem Fall muss es ja wieder hin.
Man hätte da einfach nur Klammern setzen müssen ;)
Dann kannste $FFFF nehmen, oder $F000 oder sonstwas <)
Syntacks_Error
Beiträge: 107
Registriert: 08.03.2009 16:08

Re: Übersetzung Java => PB

Beitrag von Syntacks_Error »

Aha. Verstehen tue ich das allerdings nicht. Leider gibt es immer noch einige Probleme, irgendwie kommen nicht so ganz die exakten Werte raus, warum auch immer. Sehe es schon kommen, daß ich da einen professionellen Auftrag erteilen muß :-)
Benutzeravatar
TomS
Beiträge: 1508
Registriert: 23.12.2005 12:41
Wohnort: München

Re: Übersetzung Java => PB

Beitrag von TomS »

Hä?
Danilo hat doch bestätigt, dass das gleiche rauskommt?
Wenn du uns die "exakten Werte" mitteilen würdest, könnte man vielleicht herausfinden, wie dein PB-Code aussehen soll.

Zum verständnis: Eine Variable vom Typ Long (=Integer auf 32bit Systemen) besteht (wie der Name "32bit System" vermuten lässt) aus 32 bits.
Also 32 "Schaltern", die jeweils an oder aus sein können (1 und 0).
So eine Long-Variable kann man aufteilen in 2 Word-Variablen (Word = 2Byte = 16bit = 2^16 = ~65k).
Diese "Words" nennt man dann Hi(gh) Word und Lo(w) Word. Also hohes Word und niedriges Word.
Das HiWord steht als erstes.
(Beispiel aus dem 10er System: Ich kann 100.000 aufteilen in 2 Gruppen die jeweils 100 groß sind.
Also kann ich in 100.000 genau zwei Zahlen speichern, die beide maximal 100 groß sind.
a = 99
b=500
summe = 99.500 = 100*99 + 500).

Nachdem aber alle Variablen letztendlich binär gespeichert sind, also wieder als 1 und 0,
kann ich anstatt zu multiplizieren, einfach die bits nach vorne schieben, wie beim ausschreiben der Zahl oben^^

Das macht "<< 16".
Es schiebt den Wert 16 bits nach vorne, also an die HiWord-Position.
Dementsprechend gilt.
summe = a<<16 + b (anstatt + wird bei solchen Aktionen halt | verwendet (warum auch immer, in PB zumindest macht es (meistens (meiner Erfahrung nach immer)) keinen Unterschied).
Oder auch. summe = a * 2^16 + b

Beim Rückwandeln wird das HiWord wieder um 16 bits verschoben. Diesmal in die andere Richtung, also an die LoWord Position.
Das Rückwandeln geht im Gegensatz zum Umwandeln nur mit der binären Operation Bitshift (eben das Verschieben der Bits um 16 Stellen (in dem Fall, man kann natürlich auch um 7 oder 3 Stellen verschieben, wenn das Sinn ergibt)).
Wenn du einfach durch 2^16 teilen würdest, hättest du ja einen Rest (eigentlich das LoWord).
Aber mit normaler mathematischer Division bekommst du keinen Rest, sondern einen u.U. arg hässlichen Dezimalbruch.
Je nach Größe des LoWords bekomsmt du also auch mit Runden ein falsches Ergebnis für das HiWord heraus.
Deswegen: BitShift um 16 Stellen.

Das eigentliche LoWord bekommst du heraus, indem du die Summe mit $FFFF "maskierst"
$FFFF in Binär ausgedrückt sind 16Bit. (also genau die Word-Größe).
Da wird ja auch eine 0 haben, die auch irgendwo Platz haben muss, sind $FFFF aber nicht 2^16, sondern 2^16-1.
Binär ausgedrückt: 16 Einser nach einander.
Von den Bits vor den 16 Bits ist keine Rede und es gilt, was bei unseren täglichen Zahlen auch gilt:
Führende Nullen werden weggelassen.
Wenn man jetzt die vollen 32bit beachtet, anstatt nur 16bit, stehen da nicht nur 16 Einser, sondern auch 16 Nuller.
$FFFF als Long in Binär ist also:
00000000000000001111111111111111

Und unser LoWord (312 als Beispiel sieht so aus)
00000000000000000000000100111000

Untereinanander geschrieben.

Code: Alles auswählen

00000000000000001111111111111111
00000000000000000000000100111000
Jetzt werden nur die Bits gesetzt, die in der "Maske" ($FFFF) auch gesetzt sind.
Das sind in dem Fall alle 16.
Also werden alle 16 Bits übernommen uns es kommt wieer 312 raus.

Ich könnte als Maske auch $C nehmen. Das ist 12 im Dezimalsystem und 1100 im Binärsystem.
Als Beispiel nehmen wir wieder 312.

Code: Alles auswählen

Debug RSet(Bin($c),16,"0")
var = 312
Debug RSet(Bin(var),16,"0")

Debug Bin(var & $C)
Debug var & $C
Das Ergebnis:

Code: Alles auswählen

0000000000001100 ;$C <- Maske 
0000000100111000 ;312 im Binärsystem
0000000000001000 ;Nur die Bits sind 1, die in beiden Bitsequenzen 1 sind.
8 ;Das Ergebnis im Dezimalsystem 
Diese Maskierung mit anderen Werten als $FFFF ergibt imho eigentlich gar keinen Sinn.
Damit kastriert man nur den Eingabewert und das ohne Rückmeldung.
Speicherplatz wird dadurch auch keiner gespart. Die Variable ist immer noch 4Byte groß, egal welche Maskierung man verwendet.

Lange Rede kurzer Sinn:
Auch wenn ich oben gezeigt habe, wie man eine Maskierung von $XYZ anwendet: Weglassen geht genauso.

Code: Alles auswählen

i5.i = 312
i6.i = -3109
j8.i = i6 << 16 | i5
Debug j8.i
Debug j8 >> 16
Debug j8  & $FFFF
Antworten