Gå til innhold

Bitwise operatører = Vanskelige saker


Anbefalte innlegg

Det er noe jeg sliter med og det bitwise operatører. Jeg får dem ikke inn i hode. Hititl har jeg forstått at det er 3, operatører som er &, |, ^. Ikke skjønner jeg hvordan de sammelignes heller når man bruker de og hva de er til. har også sett at man kan ta assigment med = ved siden. Skjønner heller ikke det. Og det jeg forstår ingenting av er << og >> operatørene..

 

Boka har brukt dette eksemplet her

 

Håper noen kan forklare meg om disse tingene så jeg kan fortsette på dettte stuff'et

Lenke til kommentar
Videoannonse
Annonse

du har

val & (1 << i)

 

først utføres 1 << i, og denne gir et resultat, så utføres & med val og det foregående resultatet som argumenter - altså det kan splittes opp, noe slikt:

 

int val, i, temp, result;
temp = 1 << i;
result = val & temp;

 

så da er spørsmålet delt i to;

 

* hva gjør 1 << i ...?

* og hva gjør val & temp ...?

 

du kan vel svare på dette? :)

Endret av lnostdal
Lenke til kommentar

1. Er ikke 100% sikker men tror:

 

Det flytter en tallet "i" plasser bortover...

 

2. val & temp:

 

Den tar bitsene i val og temp, og der begge er 1, så settes det 1, eller så settes det 0.

 

Hvorfor går det i if forresten? Er det mulig at den kan gi false på sånt?

Endret av Zic0
Lenke til kommentar

(edit: skrevet i hui og hast; skal lese over denne i morgen - så ta forbehold om feil og slikt)

 

Angående << så _forskyver_ den bittene i tallet 1 i plasser mot venstre. Husk at disse _bitwise_ operatørene hele tiden jobber med de binære representasjonene av dataene. Dette ser slik ut:

 

0001  (tallet 1 representert som binary)
<<
0010  (tallet 2 representert som binary)

 

Hadde man brukt << en gang til ville man fått:

 

0010 (tallet 2 representert som binary)
<<
0100 (tallet 4 representert som binary)

 

Det du nevner om operatøren & er riktig.

 

...så til dette med precedence, og hvordan if mottar en verdi i denne sammenhengen...

 

Du må hele tiden tenke på at operatører som & og << returnerer verdier, eller det vil si - de returnerer resultatet av operasjonen de utfører, på samme vis som at i uttrykket 3 + 2 så returnerer operatøren + summen av 3 og 2.

 

Man kan i grunn tenke seg at alle operatører er definert som funksjoner som tar 2 argumenter (det er faktisk en som tar 3; du kommer til den siden) og returnerer et resultat. Altså slik:

 

int my_plus(int a, int b){ return a + b; }
int my_minus(int a, int b){ return a - b; }
int my_bitwise_and(int a, int b) { return a & b; }
int my_bitwise_lshift(int a, int b] { return a << b; }

 

Her kan vi tenke oss at språket C/C++ ikke lengre har ting som +, -, & og <<, men at de er erstattet med funksjonene my_plus, my_minus o.s.v.. Da ser du med en gang at:

 

if(my_bitwise_and(val, my_bitwise_lshift(l, i)))
 cerr << "result is not 0 (ie. not false" << endl;
else
 cerr << "result is 0 (ie. it's false)" << endl;

 

..if'en tar resultatet av my_bitwise_and-operasjonen. Dette foregår altid slik at ting starter helt "innerst og jobber seg utover".

 

Altså om square er en funksjon som returnerer kvadratet av argumentet den mottar (int square(int x) { return x * x; }) så blir:

 

square(square(square(2)))

 

256 - altså den ytterste square-funksjonen returnerer 256. Man kan dele opp dette slik som jeg gjorde i forrige post her:

 

int temp1, temp2, temp3;
temp1 = square(2);
temp2 = square(temp1);
temp3 = square(temp2);

 

..men man ser enkelt at den kan forkortes, fordi resultatet av square(2) blir kun brukt én eneste gang i form av temp1 til argument for neste square-kall - så da gjør man det i stedet direkte ved å fjerne mellomleddet temp1:

 

int temp2, temp3;
int temp2 = square(2);

 

..o.s.v.. ..regner med at du henger med her?

 

Måten ting jobber seg fra innsiden og utover i square gjør seg også gjeldende i alle andre slike sammenhenger. Den innerste my_bitwise_lshift returnerer resultatet av sine to argumenter, videre tar my_bitwise_and verdien val og resultatet fra den inndre my_bitwise_lshift og returnerer på nytt et resultat til den ytterste "funksjonen" if.

 

Tilbake til det orginale tilfellet:

 

if(val & (1 << i))

 

For å finne ut hva som skjer først-og-sist i et uttrykk som består av flere operatører etterhverandre; val & 1 << i, eller val & (1 << i) eller f.eks. 6 + 3 * 3 + 4 / 2 må man se på noe som kalles operator precedence. I matte må man f.eks. gange før man plusser. Sånn er det i C/C++ også, men her har man også et par operatører som ikke er like vanlige i matte.

 

En spesiell operatør er parantesen som egentlig ikke gjør noe, men i stedet eksplisitt spesifiserer rekkefølge på operasjoner. Dette er på samme vis som i matte.

 

I språk som Lisp er det mye enklere; der finnes ikke _operatører_ som +, -, & og <<. De er i stedet erstattet med _funksjoner_, derfor er det aldri noen tvil om hva som skjer når.

 

(6 + 3) * (3 + 4)
-----------------
        2

..blir i Lisp:


(/ (* (+ 6 3) (+ 3 4))
   2)

..mens i C/C++ blir det:

((6 + 3) * (3 + 4)) /
         2

 

Så i Lisp bruker man vanlige funksjons-kall hele tiden, som i square-eksempelet, uten å måtte tenke på rekkefølge av operasjoner. T.o.m. if er en funksjon som returnerer en verdi(!). I matte-sammenheng kalles dette prefix-notasjon, i motsetning til den vanlige infix-notasjon (google frem disse). (men man kan også fikse infix-notasjon i Lisp om man ønsker det, les: Programmerbart Programmeringsspråk)

 

Oh, må legge til at 0 er det samme som false i C++, mens alle andre verdier utenom 0 er true. Snakker om if nå altså.

 

Uansett .. om du noen gang er i tvil er det bare å bruke paranteser; ting blir ofte lettere å lese med paranteser, selv om du kanskje vet at de er unødvendige.

 

...vel, håper dette er forståelig... :devil:

Endret av lnostdal
Lenke til kommentar

if(val & (1 << i))

det denne gjør er at den sjekker om bit nr. i er satt.

du kan f.eks ha int val = 13 = 1101

hvis du vil ha binærrepresentasjonen av den, så starter du på den nederste biten (den lengst til høyre) og sjekker om den er satt eller ikke, også går du videre til neste bit..

1101 & (1 << 0) = 1101 & 0001 = 1

1101 & (1 << 1) = 1101 & 0010 = 0

1101 & (1 << 2) = 1101 & 0100 = 1

1101 & (1 << 3) = 1101 & 1000 = 1

nå ser du at du har tallet 13 i binærrepresentasjon hvis du leser nedenfra og opp

Endret av teflonpanne
Lenke til kommentar
*Masse*

 

 

if(val & (1 << i))

det denne gjør er at den sjekker om bit nr. i er satt.

du kan f.eks ha int val = 13 =  1101

hvis du vil ha binærrepresentasjonen av den, så starter du på den nederste biten (den lengst til høyre) og sjekker om den er satt eller ikke, også går du videre til neste bit..

1101 & (1 << 0) = 1101 & 0001 = 1

1101 & (1 << 1) = 1101 & 0010 = 0

1101 & (1 << 2) = 1101 & 0100 = 1

1101 & (1 << 3) = 1101 & 1000 = 1

nå ser du at du har tallet 13 i binærrepresentasjon hvis du leser nedenfra og opp

6566111[/snapback]

 

 

Tusen takk for hjelpen. satte mangelen på kunnskap på plass. You are the men! :w00t:

 

EDIT: Det med at den sjekker bit'en og går videre. Skjer det automatisk, etter hvor mange ganger den sjekker, eller er det noe system på det? For eksempel sjekker den bit'ene som er plasser, hvor den ene ble flyttet til.?

Endret av Zic0
Lenke til kommentar
EDIT: Det med at den sjekker bit'en og går videre. Skjer det automatisk, etter hvor mange ganger den sjekker, eller er det noe system på det?

 

Vel det teflonpanne (tror jeg:)) viser er hvordan sammenhengen mellom C funsjoner og resultat og binære operasjoner

[C Funsjonen___]_[binære operasjon] resultat

1101 & (1 << 0) = 1101 & 0001 = 1

 

hver enkelt av linjene er en funsjon og det er kun en linje som blir utført, ingen automatik

 

For eksempel sjekker den bit'ene som er plasser, hvor den ene ble flyttet til.?

6566822[/snapback]

 

Jeg er muligens litt gåen i varmen, men jeg skjønner ikke hva du mener.

Men ingenting blir forandret i funksjonene dvs. alle variablene kan være const uten at det ville ha noen virkning.

 

funksjonen flytter 1 slik at den er i samme posisjon som bittet som skal skjekkes om eksister så utføres en AND (OG) funsjon resultatet blir returnert

Endret av Giddion
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...