1 van 2

Stukje java code.

Geplaatst: di 03 jul 2007, 17:42
door Bert F
Kan er mij iemand volgend stukje java uitleggen?

// build an int from a byte array - convert little to big endian

public static int constructInt(byte[] in,int offset) {

int ret = ((int)in[offset + 3] & 0xff);

ret = (ret << 8) | ((int)in[offset + 2] & 0xff);

ret = (ret << 8) | ((int)in[offset + 1] & 0xff);

ret = (ret << 8) | ((int)in[offset + 0] & 0xff);

return(ret);

}

Ik heb nog nooit een & gebruikt wel een && en ook nog nooit een | wel || wat bedoelt men met die 0xff is dat gewoon 255?

de int begrijp ik wel (net voor in) dit is om een conversie naar int te forseren.

Maar verder heb ik het raden naar de werking van dit stukje.

Groeten.

Re: Stukje java code.

Geplaatst: di 03 jul 2007, 19:21
door Brinx
Die routine 'bouwt' een integer van een selectie van 4 opeenvolgende bytes uit een array losse bytes die hij aangeleverd krijgt (de 'in[]' array). Hiervoor gebruikt hij onder andere de zogenaamde 'bitwise AND' en de 'bitwise OR': deze operaties vergelijken individuele bits en geven als uitkomst telkens 0 of 1. Eerst een korte uitleg over deze twee operaties:

Bij een bitwise 'AND' operatie (symbool '&') vergelijk je twee bits, en als deze beide '1' zijn is de uitkomst ook '1', anders is de uitkomst '0'. Deze vergelijking kun je ook uitvoeren op hele bit-arrays ('00101010' is een bit-array van 8 elementen, dus een byte) en zo vorm je een nieuwe bit-array die '1'tjes heeft staan op de plaatsen waar beide inputarrays dat ook hebben, en '0' op alle andere plekken.

Een voorbeeld:

01100110 & 11000101 = 01000100

Waarom?

Code: Selecteer alles

01100110

11000101 &

--------

01000100
Je ziet dat de output-array alleen maar 1'tjes heeft waar beide inputarrays 1'tjes hadden staan.

'Bitwise OR' (symbool '|') is bijna hetzelfde, alleen heeft de output-array nu 1'tjes waar op zijn minst een van beide inputarrays een 1'tje had staan. Gebruiken we de vorige inputarrays nog eens hiervoor, dan krijgen we:

01100110 | 11000101 = 11100111

Code: Selecteer alles

01100110

11000101 |

--------

11100111
Goed, nu verder naar de routine die je postte. De routine pakt 4 bit-arrays van 8 elementen elk (bytes dus) en 'naait' die aan elkaar tot een grote bit-array van 32 bits: een integer (die dus een grootte heeft van 4 bytes). Die 4 bytes worden achterstevoren achter elkaar gezet (vandaar het 'convert little to big endian: little-endian en big-endian zijn manieren om getallen van meerdere bytes op te slaan, geloof ik: de ene of de andere kant op). Hierbij wordt ook 'bit shifting' gebruikt:

Bijvoorbeeld een bit-shift van het getal 9 (bit-array '00001001'):

00001001 << 4 = 10010000.

Hierbij is de hele serie bits gewoon 4 plaatsen naar links opgeschoven, en zijn de vrijgekomen plaatsen opgevuld met nullen. Omdat iedere bit-shift naar links overeen komt met een vermenigvuldiging van 2, resulteert die bit-shift van net in een getal dat 16 keer zo groot is als 9: namelijk 144 (tel na!).

Een bit-shift van 8 plaatsen naar links, zoals in de code gebeurt, komt dus overeen met het verminigvuldigen van het getal met 256 (2^8). Daarmee wordt dus ruimte gemaakt voor de volgende 8-delige bit-array die ingevoegd wordt - en zo wordt de lange bit-array van 32 elementen opgebouwd uit 4 kortere van 8 elementen elk.

Re: Stukje java code.

Geplaatst: wo 04 jul 2007, 08:45
door Nvt
Wat gaat sneller, bit-shiften of vermenigvuldigen?

Re: Stukje java code.

Geplaatst: wo 04 jul 2007, 09:01
door Bert F
een beetje verder staat er (niet in dit stukje code) |= is dit een exclusieve of?

Re: Stukje java code.

Geplaatst: wo 04 jul 2007, 13:24
door Nvt
een beetje verder staat er (niet in dit stukje code) |= is dit een exclusieve of?


Bitsgewijs Exclusief Of, xor: ^

Re: Stukje java code.

Geplaatst: wo 04 jul 2007, 17:56
door Bert F
Merci voor de antwoorden.
Wat gaat sneller, bit-shiften of vermenigvuldigen?
Bedoel je snelheid kwa cpu? geen idee. Denk eerder dat je het gebruik van dat moet zoeken in het al dan niet "handig" omspringen met die zaken, denk niet dat ik dit ooit zelf zou gebruiken.

Groeten.

Re: Stukje java code.

Geplaatst: wo 04 jul 2007, 20:05
door Nvt
Bedoel je snelheid kwa cpu? geen idee. Denk eerder dat je het gebruik van dat moet zoeken in het al dan niet "handig" omspringen met die zaken, denk niet dat ik dit ooit zelf zou gebruiken.
Nee, wat betrefd de snelheid van de uitvoering van het programma.

Ik heb eens een keer een klein progje gemaakt wat uuEncode van usenet kon decoderen. Had ik eerst een voorbeeld op internet gezocht, maar de code begreep ik niet, was iets met delen. De uitleg echter wel, in het kort: van 4 bytes moet je 3 bytes maken. Gaat met bit-shifting. Maar je kan dus ook dmv een vermenigvuldiging / deling "bit-shiften".
Een bit-shift van 8 plaatsen naar links, zoals in de code gebeurt, komt dus overeen met het verminigvuldigen van het getal met 256 (2^8).
Zodoende vroeg ik met af wat sneller zou gaan.

Re: Stukje java code.

Geplaatst: wo 04 jul 2007, 23:40
door Cycloon
Volgens mij is het grote nadeel van bit-shiften dat je enkel met machten van 2 kan vermenigvuldigen (je gaat gewoon de rang van elke waarde gaan verschuiven). Vermenigvuldigen met 3 zit er bv niet in. Zoals Bert F. zei: Het hangt een beetje af van situatie tot situatie.

Re: Stukje java code.

Geplaatst: do 05 jul 2007, 00:43
door Nvt
Dus een bit shif statement gaat dan net zo snel als een vermenigvuldiging.

Stel ik wil de bits een x-aantal plaatsen naar rechts shiften, ik was eerst aan deling aan het denken.

Maar ik denk dat het ook met vermenigvuldigen kan.

Bijv:

Bits 2 plaatsen naar rechts dmv: waardeByte * (2^ -2), klopt dit?

Dan zou je alleen nog rekening moeten houden met berekeningen die een gebroken getal opleveren.

Re: Stukje java code.

Geplaatst: do 05 jul 2007, 08:38
door EvilBro
Dit is niet handig (sterker nog: stom). Je moet geen rare truuks gaan uithalen in je programma's. Je moet gewoon programmeren wat je bedoelt. Dus een 'right shift' doe je met een 'right shift'. Delen door twee doe je met "/2". Pas op het moment dat met een profiler blijkt dat je 'performance issues' hebt, dan pas ga je truuks toepassen.

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." (Code Complete, Page 594)

Re: Stukje java code.

Geplaatst: do 05 jul 2007, 09:57
door Cycloon
Nvt schreef:Bijv:

Bits 2 plaatsen naar rechts dmv: waardeByte * (2^ -2), klopt dit?


Ja klopt.

Re: Stukje java code.

Geplaatst: do 05 jul 2007, 10:50
door EvilBro
Ja klopt.
Hoewel het wiskundig gezien hetzelfde is, wil ik toch wel enkele kanttekeningen plaatsen:

2^(-2) is niet een integer. Dat heeft tot gevolg dat of het geheel wordt omgezet naar een double, of de waarde wel in een integer wordt gestopt maar niet een zinnige waarde krijgt. Beide situaties leveren geheid problemen op.

De compiler compileert waarschijnlijk "/2" en ">> 1" naar dezelfde code. Dit is nog een reden om code simpel te houden (dan kan de compiler beter optimaliseren).

Re: Stukje java code.

Geplaatst: do 05 jul 2007, 16:11
door Bert F
het grootte verschil is (zie het ook nu pas in) dat je eigenlijk gaat schuiven en niet roteren zo als ik gisteren nog dacht.

dus: we gaan altijd over naar de binaire voorstelling we hebben bv 6 dan zal 0110 in bin.

omdat 8 4 2 1 de "machten" van twee zijn na 1 bitshift hebben we:

1100 zodat 12 volgt.

nog een keer bitshiften oftwel 6 2keer shiften geeft 24 en niet 3 zie je waarom ik dat eerst dacht?

Als je nu files wil uitlezen en je getal te lezen bestaat uit 2 bytes dan heeft die 2de byte meer waarde dan de eerste zie je? dat los je gemakkelijk op met dit shift gedoe.

Groeten.

Re: Stukje java code.

Geplaatst: do 05 jul 2007, 16:20
door EvilBro
Ik heb geen idee wat je probeert te zeggen.

Re: Stukje java code.

Geplaatst: do 05 jul 2007, 16:38
door Nvt
Ik denk dat het verstandiger is om voor een bestand te lezen/schrijven een of andere stream uit de java-api te gebruiken :D