9. hét: számábrázolás, bitműveletek

Czirkos Zoltán · 2019.08.03.

Gyakorlófeladatok az előadás anyagához kapcsolódóan.

1. Bitműveletek

Mennyi?

Mennyi 27|13? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás
  27 = 11011
 |13 = 01101
––––––––––––
  31 = 11111

Mennyi 45&57? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás
 45 = 101101
&57 = 111001
––––––––––––
 41 = 101001

Mennyi 27^13? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás
 27 = 11011
^13 = 01101
–––––––––––
 22 = 10110

Mennyi (~20) & 13? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás
 20  =       10100
~20  = ...11101011
&13  =    00001101
–––––––––––––––
   9 =    00001001

Mennyi 0x2A | 0x82? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tizenhatos számrendszerben is add meg!

Megoldás
 0x2A = 00101010
|0x82 = 10000010
––––––––––––––––
 0xAA = 10101010

Mennyi 20|13? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás
 20 = 10100
|13 = 01101
–––––––––––
 29 = 11101

Mennyi 42&54? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tízes számrendszerben is add meg!

Megoldás
 42 = 101010
&54 = 110110
––––––––––––
 34 = 100010

Mennyi 0x2A ^ 0x36? Írd le mindkét számot, valamint az eredményt is kettes számrendszerben! Az eredményt tizenhatos számrendszerben is add meg!

Megoldás
 0x2A = 101010
^0x36 = 110110
––––––––––––––
 0x1C = 011100

Mennyi (~22) & 10? Írd le 22-t, ~22-t és 10-et, valamint az eredményt is kettes számrendszerben!

Megoldás
 22 =    010110
~22 = ...101001
 10 =    001010
––––––––––––
  8 =    001000

Műveletek kettes számrendszerben

Végezzük el az alábbi műveleteket kettes számrendszerben! Tízesben tudjuk, hogy kell... De megy kettesben is? Mennyiben más?

 101101
+110111
–––––––
 101101×1011
 ––––––
 

Hexadecimális

Készíts programot, mely a felhasználó által megadott decimális számot átváltja 16-os számrendszerbe (hexadecimális), és az eredményt kiírja a képernyőre. (Ehhez a .format()-tal is lehet ügyeskedni.)

Igazságtábla – kevés bitre

Készíts programot, mely elkészíti az alábbi logikai függvények igazságtáblázatát, és kiírja a képernyőre: a.) ÉS b.) VAGY c.) NOT d.) NOR e.) XOR.

Igazságtábla – sok bitre

ABC|Q
–––+–
000|0
001|0
010|0
011|0
100|0
101|0
110|0
111|1

Készíts programot, amelyik az ÉS, VAGY, KIZÁRÓ VAGY függvény igazságtábláját készíti el, a felhasználó által megadott bemenetszámra! Például 3 bites ÉS igazságtábla esetén a jobb oldali legyen a kimenet.

Megoldás

A feladat érdekes része a ciklus megírása: nem ágyazhatunk egymásba a programkódban annyi ciklust, ahány bitünk lesz, hiszen a számuk csak a megoldás közben derül ki. Viszont tudjuk, hogy pl. 4 bit esetén 0000-tól 1111-ig megyünk; az 1111 értéke (vagy éppen 10000 értéke) meghatározható bitműveletekkel.

Bináris szám megadása

Írj programot, mely bekér egy max 16 hosszú bitsorozatot karakterlánc formában karakterenként úgy, hogy csak 0-ás és 1-es karakterek bevitelét engedélyezi. A bevitel végét az enter megnyomása jelzi. Ezután írja ki az ilyen módon kettes számrendszerben megadott szám tízes számrendszerbeli alakját! (Elsőleg legnagyobb helyiértéket adja meg a felhasználó.)

Egyszerű bitműveletek

Írj programot, amelyik kér egy nemnegatív számot. Írja ki ezt a számot binárisan. Utána állítsa 1-be a 7. bitjét; állítsa 0-ba a 6. bitjét, és végül negálja a 0. bitjét. Írja ki az így megváltoztatott számot!

Bitek cseréje – adott sorszámú bitek

Írj egy programrészt, amelyik egy nemnegatív egész számban megcseréli két adott sorszámú bitjét! Az így keletkező számot kell előállítani. A 0. bit a legkisebb helyiértékű.

Tükrözve

Készíts programot, mely egy unsigned char típusú változóban tükrözi a biteket, vagyis a legnagyobb helyiértékű bit helyet cserél a legkisebbel (0↔7), a második legnagyobb a második legkisebbel (1↔6) stb.

Adott bitek invertálása

Írj olyan programrészt, amely egy előjel nélküli x számban p pozíciótól kezve n bitet invertál! Például bemenet: x=10110 (binárisan), p=2, n=3-ra a kimenet x=01010.

Bitsorozat kivágása

Írj programrészt, amely paraméterként kap három egész számot (szam, honnan, db)! A programrész vegye ki a szam jobbról honnan sorszámú, db számú bitet tartalmazó tartományát, és ezt adja meg! Pl. Be: 471, 3, 5 → 471=111010111 → 10101, tehát a kimenet: 21.

Hány eltérő megoldást lehet találni?

Páros számú 1-es bit

Írj programrészt, amely bemenetként kap egy pozitív egész számot, és logikai igazat állít elő, ha a szám páros számú 1-es bitet tartalmaz!

Mind a 32 bit cseréje

Írj programrészt, amely bemenetként kap egy előjel nélküli egész számot, melyről feltételezzük, hogy 32 bites. Cserélje fel a szám összes szomszédos bitpárját (0. az 1.-vel, 2. a 3.-kal, … 30. a 31.-kel)!

Bitek cseréje – bármekkora változóra

Írj egy olyan programrészt, amely bemenetként kap egy előjel nélküli egész számot, és kimenetként szintén egy előjel nélküli egész számot állít elő! Az utóbbi szám úgy keletkezik, hogy a paraméterként átvett számban megcseréli a szomszédos bitpárokat. Nem tudjuk, hogy az adott gépen hány bites az egész, de biztosan páros bitszámú. Pl. be: 25 → 011001, ki: 100110 → 38.

Megoldás

Itt a 0. bittől érdemes haladni. Két dologra kell figyelni:

  • Mindig az i. és az i+1. bitet cseréljük; utána i-t 2-vel növeljük.
  • És ezt addig csináljuk, amíg a számból ha levágjuk az utolsó i bitet, akkor az eredmény nem 0. Mert ha 0, akkor ott már nincs több 1-es, amit cserélgetni kellene – akármekkora is az int.

Hány 0 értékű bit?

Írj programrészt, amely paraméterként kap egy előjel nélküli egész számot, és megadja, hogy a szám hány 0 értékű bitet tartalmaz! A számról feltételezhető, hogy 32 bites.

Egyesek egymás mellett

Írj programrészt, amely bemenetként kap egy egész számot, melyről feltételezzük, hogy 16 bites. Adjon meg ez egy logikai értéket, amely akkor legyen igaz, ha a számban bárhol található egymás mellett két 1-es értékű bit, amúgy hamis! Pl. 138=10001010 esetén hamis a válasz, 154=10011010 esetén pedig igaz.

Mindkét oldalról 0

Írj programrészt, amely bemenetként kap egy előjel nélküli egész számot, és megadja, hogy hány olyan 1-es bit van a számban, amelyet mindkét oldalról 0 bit határol! (Értelemszerűen a legalsó és legfelső bit nem lehet ilyen.) Pl. ha a bemenő bitminta 1011101000010101011001010011111, akkor az eredmény 6. A bemeneti számról feltételezhető, hogy 32 bites.

Megoldás

Egy nem a triviális, hanem trükkös megoldás a következő. Ha egymás melletti három bitet vizsgálunk, akkor ehhez 010-t kell lássunk. A szam & 7 kifejezéssel kivághatunk három bitet (mert 7 = 111); enne értéke 010, azaz 2 kell legyen.

Pontosan hat darab 1-es

Írj programrészt, amely bemenetként kap egy pozitív egész számot, és logikai igazat ad meg, ha a szám pontosan 6 db 1-es bitet tartalmaz!

Rotálás

Írj programrészt, amely bemenetként kap két előjel nélküli egész számot (mit, db), és mit-et db számú bittel forgatja el jobbra, és ezt az értéket adja meg (az előjel nélküli egészeket 32 bitesnek feltételezzük)! A jobbra forgatás azt jelenti, hogy mit bitjei db számú bittel jobbra tolódnak, és a „kieső” bitek a szám elejére kerülnek vissza. Pl. be:
00000000111111111111101010101010 és db = 4, ki:
10100000000011111111111110101010.

Bájtsorrend

Készíts programrészt, amelyik egy 32 bites előjel nélküli szám bájtsorrendjét megfordítja. Például, ha a bemenet 0x11223344, a kimenet legyen 0x44332211. Tételezd fel, hogy a szám 32 bites!

2. Számábrázolási problémák

Végtelen ciklus?

Az alábbi program egy olyan ciklust tartalmaz, mely addig fut, amíg egy szám és egy nála eggyel nagyobb szám nem egyenlő egymással. Ha a lebegőpontos típusaink végtelenül pontosak lennének, ez végtelen ciklust eredményezne. Mi a helyzet a gyakorlatban?

e = 0.0
f = 1.0

while e != f:
    f *= 2
    e = f+1

print(e, f)

Gyökkeresés

Tudjuk, hogy az x3-9x2+23x-15=0 egyenlet egy gyöke 2.2 és 4.5 között található. Írj programot, amely intervallumfelezéses módszerrel kiszámítja az egyenlet gyökét!

Tipp

Az intervallumfelezés módszere egy x_also és egy x_felso értékből indul ki, az ezekhez tartozó függvényértékekről tudjuk, hogy ellentétes előjelűek. Kiszámítjuk az x_kozepe=(x_also+x_felso)/2 értéket: ha az ehhez tartozó függvényérték előjele az x_also-hoz tartozó függvényérték előjelével egyezik meg, akkor x_also=x_kozepe, egyébként x_felso=x_kozepe. (Vagyis az x_also és x_felso távolságát felére csökkentjük úgy, hogy a gyök továbbra is a két határ között legyen.) Az eljárást addig folytatjuk, míg x_also és x_felső „elég közel” nem kerül egymáshoz (pl. epszilon=10-6). Ekkor a gyöknek x_also-t, x_felso-t, vagy az átlagukat tekinthetjük.

(x-1)(x-10n) = 0

Írj függvényt, amely megoldja az (x-1)(x-10n)=0 egyenletet! Ehhez alakítsd át az egyenletet x2-(1+10n)x+10n=0 alakba és az együtthatókat helyettesítsd be a megoldóképletbe. A függvény bemeneti paramétere n legyen. Próbáld ki a függvényt n = 1, 2, 4, 8 esetekre, egyre nagyobb számokra! Figyeld meg, hogy mi történik és adj rá magyarázatot!