[Java] Logische(!) Bitwise Operators

Pagina: 1
Acties:
  • 104 views sinds 30-01-2008
  • Reageer

  • mrClass
  • Registratie: April 2002
  • Laatst online: 17-04-2025
Die moet ik even kwijt: Ik vind java de meest inconsistente waardeloze taal die op deze aarbol groot is geworden, en wel om het volgende:

Als je eens lekker wilt bitshiften in Java, dat heb je meteen al een groot scala aan problemen waar je tegenaan loopt. Deze problemen lijken verreweg van logisch. Maar misschien ziet iemand een rationele verklaring in de volgende feiten:

De ellende begint al, als je een unsigned integer type wilt, die bestaan simpelweg niet!. En ja, ik weet wel dat Java een OO taal is. Nou maakt het dan compleet OO en niet een beetje, en als je het een beetje wilt doen. Doe het dan een beetje goed!

Probeer namelijk maar een een Signed type in Java te bitshiften. Ja dat gaat lekker fout. De signed bit shift namelijk gewoon niet mee. Daar gaat de essentie van bitshiften.

Owk ze hebben een oplossing gevonden namelijk de >>> operator. En wat doet deze: Hij kopieerd :? de singed bit naar rechts en de rest shift hij gewoon!. Ja handig! Alleen DIT is geen bitshiften. Het hele verschuif idee help je hiermee dus om zeep!

Nou ja hier valt nog wel overheen te komen, en stiekum kent Java toch wel 1 unsigned type: char!. leve de char! Die waan laat je ook wel snel varen. Probeer maar eens van een byte een char te maken. Dan heb je acht bits over, want char is 16 bits en byte is 8 bits. Logischerwijs zou je denken dat je gewoon dit kan doen: mychar = (char)mybyte. En weet je wat Java dan doet?!. Hij vult de most significant bits met 1'nen!! |:( Om het ff in code samen te vatten treden de volgende singulariteiten op:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(pseudo)
byte type (-128 t/m +128) :
10000011 =  -67
11000011 >>  1 = 10100001  (Hij laat de singed bit gewoon staan!! freak!)
11000011 >>> 1 = 11010001  (Ja..nee. dit is logisch shiften! :? )

char type: (0 t/m 65535)
byte naar char:

mychar  =  (char) 01000100
En wat is mychar nu: 1111111101000100
Lekker hoor, alles met 1nen aanvullen!

Dus om dit goed te kunnen doen moet je dit doen:
mychar  = (char) (01000100 << 8)
mychar  = mychar >> 8

nu staat wel de gewenste waarde in mychar!


Myn conclusie is dat om fatsoenlijk te bitshiften, je genageld bent aan een 16 bits karakter type!. Van alle andere kun je gewoon 1 bit weggooien, als je bitwise wilt manipuleren! Maar niet te praten over de rest van de problemen die je dan krijgt.

Ik hoop dat mijn punt een beetje duidelijker is, dan het bitshiften in Java.

Dit vind ik niet echt logisch. En ik zou ook graag willen weten waarom dit zo werkt. En of er een meer C++ of Delphi(!) manier is om dit een beetje in goede banen te leiden?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Volgens mij ligt het eerder aan bugs in jouw code, want Java doet het prima hoor :z
Ik zal eens een testje bouwen

.edit: overigens, je bent op de hoogte dat de bitwise operatoren alleen werken op ints en longs, en dat een operatie op een byte 'm dus eerst zal converteren naar een int?

Je verwacht natuurlijk dat als je een (byte)-67 hebt, en je doet dat >>> 1, dat je dan 94 eruit krijgt. Echter, de byte converteren naar int zal bits 8 t/m 31 op 1 zetten omdat het een negatief getal is. De logical shift right zal de 1 van plaats 8 dan ook op 7 zetten, terwijl daar een 0 zou moeten komen te staan als het echt een byte was geweest. Maar het is geen byte, het is een int, en dus is het resultaat ook niet 94 maar -34, hetzelfde als een arithmetic shift right dus, zodra je het weer terugcast naar een byte

[ Voor 93% gewijzigd door .oisyn op 25-05-2004 18:25 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

mrClass schreef op 25 mei 2004 @ 17:56:
Die moet ik even kwijt: Ik vind java de meest inconsistente waardeloze taal die op deze aarbol groot is geworden, en wel om het volgende:
Java is idd stom ;) netzoals meisjes ;)
De ellende begint al, als je een unsigned integer type wilt, die bestaan simpelweg niet!. En ja, ik weet wel dat Java een OO taal is. Nou maakt het dan compleet OO en niet een beetje, en als je het een beetje wilt doen. Doe het dan een beetje goed!
Unsigned ints hebben niets te maken met oo.

  • Domokoen
  • Registratie: Januari 2003
  • Laatst online: 20-05 14:26
Als je nu gewoon uitgaat dat er maar 31 bits bruikbaar zijn van een 32-bits type, dan lijkt Java ineens heel consequent (de sign bit doet gewoon niet mee).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mr.Chinchilla schreef op 25 mei 2004 @ 18:22:
Als je nu gewoon uitgaat dat er maar 31 bits bruikbaar zijn van een 32-bits type, dan lijkt Java ineens heel consequent (de sign bit doet gewoon niet mee).
sorry maar daar klopt niets van :)
De laatste bit kun je net zo goed gebruiken, je moet er alleen niet vanuit gaan dat het getal gerepresenteerd door die 32 bits niet unsigned is

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

mrClass schreef op 25 mei 2004 @ 17:56:
Die moet ik even kwijt: Ik vind java de meest inconsistente waardeloze taal die op deze aarbol groot is geworden, en wel om het volgende:
Gebruik het dan niet ;)
(ook al ben ik het niet met je eens)
Als je eens lekker wilt bitshiften in Java, dat heb je meteen al een groot scala aan problemen waar je tegenaan loopt. Deze problemen lijken verreweg van logisch. Maar misschien ziet iemand een rationele verklaring in de volgende feiten:
Gelukkig doen de meeste java-programmeurs niet zo aan bitwise rekenen :P
De ellende begint al, als je een unsigned integer type wilt, die bestaan simpelweg niet!. En ja, ik weet wel dat Java een OO taal is. Nou maakt het dan compleet OO en niet een beetje, en als je het een beetje wilt doen. Doe het dan een beetje goed!
Wat heeft OO met het wel of niet beschikbaar zijn van een unsigned integer-type te maken? Het wel of niet aanwezig zijn van een signed getal lijkt me domweg een keuze, die weliswaar niet voor iedereen goed uitpakt, maar niettemin een verdedigbare keuze.
Probeer namelijk maar een een Signed type in Java te bitshiften. Ja dat gaat lekker fout. De signed bit shift namelijk gewoon niet mee. Daar gaat de essentie van bitshiften.
Dat hangt er maar vanaf wat je de essentie van bitshiften vindt, als je van mening bent dat alle bits opzij moeten (ook die sign-bit) dan is dat idd niet goed. Maar als je van mening bent dat het resultaat telt en niet hoe de bits veranderen, dan is het wellicht wel relevant om het zo te doen ;)
Een bitshift was toch min of meer equivalent aan een 2-macht? Als je dus door 2 deelt of met 2 vermenigvuldigd, dan veranderd normaliter de sign niet ('t getal blijft positief of negatief)...
En weet je wat Java dan doet?!. Hij vult de most significant bits met 1'nen!! |:( Om het ff in code samen te vatten treden de volgende singulariteiten op:
Voor die |-:( terecht is: Veranderd de waarde van het "getal" door die opvulling met 1en juist wel of juist niet? Zoja, dan is het fout, zonee, dan is het toch juist goed :?
Dit vind ik niet echt logisch. En ik zou ook graag willen weten waarom dit zo werkt. En of er een meer C++ of Delphi(!) manier is om dit een beetje in goede banen te leiden?
Op java.sun.com wordt uitgelegd hoe de JVM werkt en wellicht ook hoe het bitshiften werkt?
Specifiek: http://java.sun.com/docs/...expressions.doc.html#5121
en: http://java.sun.com/docs/...nversions.doc.html#189955
en: http://java.sun.com/docs/...onversions.doc.html#26917

[ Voor 6% gewijzigd door ACM op 25-05-2004 18:34 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-05 23:07

.oisyn

Moderator Devschuur®

Demotivational Speaker

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Main
{
    public static void main (String[] args)
    {
        byte b = -67;   // 10111101
        System.out.println (Integer.toString (b & 0xff, 2));
        b = (byte)((b & 0xff) >>> 1);
        System.out.println (Integer.toString (b & 0xff, 2));    // should be 01011110
        
        b = -67;        // 10111101
        char c = (char)(b & 0xff);
        System.out.println (Integer.toString ((int)c, 2)); // should be 10111101
        
        b = 94;         // 01011110
        c = (char)b;
        System.out.println (Integer.toString ((int)c, 2)); // should be 01011110
    }
}


Output:
code:
1
2
3
4
10111101
1011110
10111101
1011110


:z

[ Voor 15% gewijzigd door .oisyn op 25-05-2004 18:43 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1