Ëåêöèÿ 9.

Ëîãè÷åñêèå è áèòîâûå îïåðàöèè


Ëîãè÷åñêèå (áóëåâû — Äæîðäæ Áóëü) îïåðàöèè. Îïåðàíäû: ëîæü èëè èñòèíà.  ÿçûêå C ëîæü êîäèðóåòñÿ öåëî÷èñëåííûì íóëåì, èñòèíà — ëþáîå öåëîå íåîòðèöàòåëüíîå ÷èñëî (îáû÷íî 0 è 1).

 ÿçûêå C: && (È, êîíúþíêöèÿ), || (ÈËÈ, äèçúþíêöèÿ), ! (îòðèöàíèå)

x && y = èñòèíà, åñëè x èñòèíà è y èñòèíà

x || y = èñòèíà, åñëè x èñòèíà èëè y èñòèíà

!x = èñòèíà, åñëè x ëîæíî

if (x && (y || z)) …

&& (È):

x/y

0

1

0

0

0

1

0

1


|| (ÈËÈ):

x/y

0

1

0

0

1

1

1

1


! (îòðèöàíèå)

x


0

1

1

0


Ïðèìåð 1. strcmp() - ñðàâíåíèå ñòðîê. Àðãóìåíòû — äâå ñòðîêè (äâà àäðåñà, ïî êîòîðûì ëåæàò ñòðîêè — êàêîå-òî êîëè÷åñòâî ñèìâîëîâ, èäóùèõ ïîäðÿä, ïîñëå êîòîðûõ ëåæèò ñèìâîë ñ êîäîì 0).

strcmp(char *str1, char *str2) – âîçâðàùàåò 0, åñëè ñòðîêè ðàâíû; ïîëîæèòåëüíîå ÷èñëî, åñëè str1 > str2 è îòðèöàòåëüíîå ÷èñëî, åñëè str1 < str2 (ñðàâíåíèå ñòðîê — â ëåêñèêîãðàôè÷åñêîì ïîðÿäêå).

if (!strcmp(str1, str2)) { /* if (strcmp(str1, str2) == 0) */

/* ñòðîêè ðàâíû */

} else {

/* ñòðîêè íå ðàâíû */

...

}

if (N) { /* âûðàæåíèå «N” èñòèííî, åñëè N != 0 */

}

...

N = 10;

while (N--) { /* âûïîëíèòñÿ 10 ðàç */

}

Ïðî strcmp() ñì.êîìàíäó Linux “ man strcmp”.

Áèòîâûå îïåðàöèè


Ëîãè÷åñêèå áèòîâûå îïåðàöèè:

& - ïîáèòîâîå È

| - ïîáèòîâîå ÈËÈ

~ - ïîáèòîâîå îòðèöàíèå

^ - èñêëþ÷àþùåå èëè


Ïðèìåð 2. Äâîè÷íîå ïðåäñòàâëåíèå:

x = 110 (6)

y = 101 (5)

Îïåðàöèè íàä áèòàìè, ñòîÿùèìè â îäèíàêîâûõ ïîçèöèÿõ:

x & y = 100 (4)

x | y = 111 (7)


Íàèìåíüøàÿ àäðåñóåìàÿ åäèíèöà â ïàìÿòè — áàéò.

Åñëè êîäèðîâàòü ëîãè÷åñêóþ èíôîðìàöèþ áàéòàìè, òî ïîòðåáóåòÿ áîëüøå ïàìÿòè, ÷åì åñëè ïðåäñòàâëÿòü åå áèòàìè.

Âîïðîñ. Çà÷åì íóæíû áèòîâûå îïåðàöèè?

Îòâåò. Äëÿ ýêîíîìèè ïàìÿòè ïðè êîäèðîâàíèè ëîãè÷åñêîé èíôîðìàöèè.

Ïðèìåð 3. Ñåòåâîé ïàêåò — äàííûå + àäðåñà + ìíîãî ïðèçíàêîâ (õàðàêòåðèñòèêè) — êîäèðóþòñÿ ëèáî îäíè áèòîì ëèáî íåñêîëüêèìè (2-3-5) áèòàìè. Äëÿ ýêîíîìèè òðàôèêà ïðèçíàêè êîäèðóþòñÿ ìèíèìàëüíûì êîëè÷åñòâîì áèòîâ.


Äðóãèå áèòîâûå îïåðàöèè — îïåðàöèè ëîãè÷åñêîãî ñäâèãà: << è >>

Ïðèìåð 3.

int x = 110 (6) – 00000...0110

x << 2 – 000...011000 (äâà ìëàäøèõ áèòà çàïîëíÿþòñÿ íóëÿìè, äâà ñòàðøèõ áèòà «x” ïðîñòî òåðÿþòñÿ)

x >> 2 – 000...00001 (äâà ñòàðøèõ áèòà çàïîëíÿþòñÿ íóëÿìè, äâà ìëàäøèõ áèòà òåðÿþòñÿ)


Çàäà÷à 1. Ñêîëüêî áèòîâ ñîäåðæèòñÿ â öåëîì ÷èñëå (íà äàííîé àðõèòåêòóðå).

Âðîäå áû ìîæíî ðåøèòü çàäà÷ó ïðîñòî: sizeof(int) * 8 (áèòîâ â áàéòå)

Îêàçûâàåòñÿ, 8 áèòîâ â áàéòå — íå ìèðîâàÿ êîíñòàíòà.


#include <stdio.h>

int main(void) {

int x = 1; /* 00000000...00001 */

int counter = 0;

while (x) {

x <<= 1; /* x = x << 1 */

counter++; /* counter = counter + 1; counter += 1 */

}

printf("Bits in integer: %d\n", counter);

return 0;

}



Çàäà÷à 2. Íàéòè, ñêîëüêî â äàííîì öåëîì ÷èñëå åäèíè÷íûõ áèòîâ (ñóììó áèòîâ â äàííîì öåëîì ÷èñëå).


Âîçüìåì áèò 1 è áóäåì åãî äâèãàòü âëåâî, ïîïóòíî ïðîâåðÿÿ èì çíà÷åíèå ñîîòâåòñòâóþùåãî áèòà â ÷èñëå.

x = 110

summa = 0

mask = 001

ïðîâåðÿåì ìëàäøèé áèò (ñ íîìåðîì 0) x: x & mask = 0, summa = 0

ñäâèãàåì áèò âëåâî: mask <<= 1 → mask = 010

ïðîâåðÿåì áèò ñ íîìåðîì 1: x & mask = 1 => summa + x & mask = 1

ñäâèãàåì áèò âëåâî: mask <<= 1 → mask = 100

ïðîâåðÿåì áèò ñ íîìåðîì 2: x & mask = 1 => summa + x & mask = 2

...

Îòâåò: 2


#include <stdio.h>

int main(void) {

int x, mask = 1, counter = 0;

printf("Input number\n");

scanf("%d", &x);

while (mask) {

if (x & mask)

counter++;

mask <<= 1;

}

printf("Sum of bits in the number: %d\n", counter);

return 0;

}



Ïðåäñòàâëåíèå öåëûõ ÷èñåë â ïàìÿòè:

x = 1 – ïðåäñòàâëåíèå â ïàìÿòè: 00000...0001

x = -1 – êàêîå ïðåäñòàâëåíèå â ïàìÿòè?

Âî-ïåðâûõ, çíàê êîäèðóåòñÿ â ñòàðøåì áèòå (åñëè ÷èñëî îòðèöàòåëüíîå, òî ñòàðøèé áèò 1).

1) Ïðåäñòàâëåíèå îòðèöàòåëüíîãî ÷èñëà â ïðÿìîì êîäå (ïîëó÷àåòñÿ èç ïîëîæèòåëüíîãî ÷èñëî èçìåíåíèåì ñòàðøåãî, òî åñòü çíàêîâîãî áèòà):

-1 — 100000...0001

2) Ïðåäñòàâëåíèå îòðèöàòåëüíîãî ÷èñëà â äîïîëíèòåëüíîì êîäå:

x + (-x) = 0

000000...001

+ 111111...111

= 000000...000

-1 – 111111...1111

-2 – 111111...1110


Ïðîâåðÿåì, ÷òî 2 + (-2) = 0:

000000...010

+ 111111...110

= 000000...000

Ïðîâåðÿåì, ÷òî 3 + (-3) = 0:

000000...011

+ 111111...101

= 000000...000



Ïðåäñòàâëåíèå öåëûõ ÷èñåë â äîïîëíèòåëüíîì êîäå:
… -3, -2, -1, 0, 1, 2, 3, ...

1111...101, 11111...110, 11111...111, 0000...000, 0000...001, 0000...010, 00000...101, ...


Çàäà÷à 3. Íàéòè áåççíàêîâîå öåëîå ÷èñëî, ó êîòîðîãî â ñòàðøåì áèòå 1, à âî âñåõ îñòàëüíûõ — 0.

Áåççíàêîâîå ÷èñëî îáîçíà÷àåòñÿ êàê «unsigned int x” èëè ïðîñòî «unsigned x”.

Èëè «unsigned char c”.


Âàðèàíò ðåøåíèÿ 1:

#include <stdio.h>


int main(void) {

unsigned int M = -1; /* íåÿâíîå ïðåîáðàçîâàíèå òèïîâ, òàêæå ñ÷èòàåì, ÷òî îòðèöàòåëüíûå ÷èñëà ïðåäñòàâëÿþòñÿ â äîïîëíèòåëüíîì êîäå => â M âñå áèòû ðàâíû 1*/

M -= (M>>1); /* M>>1 – ÷èñëî, â êîòîðîì âñå áèòû 1, à ñòàðøèé 0 */

printf("res: %x\n", M); /* %x – ôîðìàò âûâîäà öåëîãî ÷èñëà â 16-ðè÷íîì âèäå */

return 0;

}


Âñïîìèíàåì: â ÿçûêå C 1/20 = 0, ïîòîìó ÷òî âñå îïåðàíäû â âûðàæåíèè öåëûå è ðåçóëüòàò òîæå öåëûé.

2 ñïîñîáà ïîëó÷èòü âåùåñòâåííûé ðåçóëüòàò:

1) 1./20 = 0.05 – èñïîëüçóåòñÿ íåÿâíîå ïðåîáðàçîâàíèå òèïîâ (öåëîå ÷èñëî 20 íåÿâíî ïðåîáðàçîâàíî ê âåùåñòâåííîìó) è ðåçóëüòàò âåùåñòâåííûé

2) ((double)1)/20 – ÿâíîå ïðåîáðàçîâàíèå òèïîâ ( (double)1/20 – êàêîé ïðèîðèòåò îïåðàöèé (double) è „/“?)


16-ðè÷íûå ÷èñëà — èñïîëüçóþò öèôðû 0-9 è áóêâû A (äëÿ 16-ðè÷íîé öèôðû 10), B(11), C(12), …, F(15).

25610 = 10016 = 1000000002