Sayı Tabanları
Bilgisayar programlamayla, matematik arasında çok güçlü bir ilişki vardır.Geçmişe bakarsanız, bilgisayar alanında önemli adımların, hep matematik kökenliinsanlar tarafından atıldığını görürsünüz. Bir bilgisayar programcısı için,matematikten uzak durmak düşünülemez.
Bugün ki dersimizde, biraz matematik içersine gireceğiz ve sayı sistemleriyle,Boole Cebiri (Boolean Algebra) konularını ele alacağız.
Genel kabul görmüş sayı sistemleri vardır ve içlerinde en yaygını, hepimizin gündelikhayatta kullandığı 10’luk sayı sistemidir. Yazması, okunması ve işlem yapması sonderece kolay olduğundan bunu daha çocuk yaşta öğrenir ve bu şekilde sürdürürüz.Ancak bilgisayarlar bizim gibi işlem yapabilme yetisine sahip değildir. Onlar içiniki ihtimal vardır. Bir şey ya 1’dir ya da 0. Bunu ikilik sayı sistemi olarakadlandırırız. Yani bizim yazdığımız bütün sayılar, bütün harfler ve aklınızagelen-gelmeyen bütün işaretler, bilgisayar için 0 ve 1’in kombinasyonlarından ibarettir. İşte bu yüzden bizlerin, ikilik sayı sistemine hakim olması gerekir.
Sayı sistemlerini genel olarak aşağıdaki gibi ifade edebiliriz:
[number systems]
Burada, N sayı tabanına göstermektedir. k sayının hangi hanesinde olduğumuzu ifadeederken, dk ise, ilgili sayıdaki rakamı temsil eder. Şimdi basit birörnek yapalım ve ikilik tabandaki 10011 sayısının, 10 tabanındaki eş değerini bulalım:
( d4d3d2d1d0 )2 = ( d0 . 20 ) + ( d1 . 21 ) + ( d2 . 22 ) + ( d3 . 23 ) + ( d4 . 24 )
( 10011 )2 = ( 1 . 20 ) + ( 1 . 21 ) + ( 0 . 22 ) + ( 0 . 23 ) + ( 1 . 24 ) = 19
ikilik sayı sistemi dışında, 16’lık (Hexadecimal) sayı sistemi de oldukça önemli birbaşka tabandır. 16’lık sayı sisteminde, rakamları ifade etmek için 16 adet sembole gereksinimduyarız. Bu yüzden 0 ile 9 arasında olan 10 rakamı kullandıktan sonra, A, B, C, D, E ve Fharflerini de rakam olarak değerlendiririz.
Decimal : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Hexadecimal : 0 1 2 3 4 5 6 7 8 9 A B C D E F
Hexadecimal/16’lık sayı tabanıyla ilgili aşağıdaki örneklere göz atalım:
( 3FC )16 = ( 3 . 162 ) + ( F . 161 ) + ( C . 160 ) = 768 + 240 + 12 = 1020
( 1FA9 )16 = ( 1 . 163 ) + ( F . 162 ) + ( A . 161 ) + ( 9 . 160 ) = 4096 + 3840 + 160 + 9 = 8105
( 75 )16 = ( 7 . 161 ) + ( 7 . 160 ) = 112 + 5 = 117
16’lık sayı sisteminin diğer bir ismi Hexadecimal olduğundan, bazı yerlerde,bunu ifade etmek için 16 yerine ‘H’ harfi de kullanılabilir:
( BA3 )16 = ( BA3 )H ; ( A1E )16 = ( A1E )H gibi…
Tabanlar arasında dönüştürme işlemi, üzerinde duracağımız bir başka konudur.Elinizde 16’lık sayı sisteminde bir sayı varsa ve bunu 2’lik sayı sistemiyle yazmak isterseniz önce 10’luk sayı sistemine çevirip daha sonra2’lik sayı sistemine dönüştürebilirsiniz. Ancak 16’lık ve 2’lik sayı sistemleriniçok daha kolay birbirine dönüştürmeniz mümkündür. Aşağıdaki tabloda 16’lık sayı sistemindeki rakamlar ve bunun 2’lik sayı sistemindeki karşılığı verilmiştir:
Hexadecimal : 0 1 2 3 4 5 6 7 8 9 A B C D E F
Binary ( İkilik ) : 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Bu durumu bir örnekle şöyle gösterebiliriz:
( A3F1 )H : A 3 F 1
: 1010 0011 1111 0001
16’lık tabandaki her rakamın, 2’lik tabandaki karşılığını koyduğumuzda yukardakieşitliği elde ediyoruz ve buna göre ( A3F1 ) = ( 1010 0011 1111 0001 )2eşitliğini kurabiliyoruz. (2’lik tabandaki sayıya ait boşluklar, sayının daha rahatokunması için bırakılmıştır.) Bu tarz dönüşümler, 2 ve 2’nin katında olan sayı tabanlarındarahatlıkla yapılabilir.
Hatırlarsanız, değişken tiplerinde, işaretli ve işaretsiz değişken tanımlamalarındanbahsetmiştik. Şimdi olayın biraz daha derinine inelim. Bir char, 1 byte alan kaplar ve1 byte, 8 bit’ten oluşur. Aşağıdaki kutuların her birini bir bit ve kutularınoluşturduğu bütünü bir byte olarak düşünün:
a7 a6 a5 a4 a3 a2 a1 a0
Yukardaki kutuların toplamı olan bir byte, char değişkeninin kapladığı alanı temsiletmektedir. Pozitif sayıları ifade etmeyi zaten öğrenmiştik. Sayının karşılığını, 2’lik tabanda yazarak, gerekli sonuca ulaşırız. Ancak sayımız Negatif değerliyse,işler biraz farklılaşır. Burada devreye işaret biti (sign bit) devreye girer.Yukardaki şekilde, diğer kutulardan farklı renkte olan a7 işaret bitidir. Özetle, a7 0 ise, sayı pozitiftir. Eğer a7 1 ise, sayı negatiftir.
İkilik tabandaki işaretli bir sayının, 10’luk tabandaki karşılığını şu şekilde bulabiliriz:
( a7a6a5a4a3a2a1a0 )2 = ( a7 . -27 ) + ( a6 . 26 ) + … + ( a1 . 21 ) + ( a0 . 20 )
İkilik tabanda yazılmış ( 10000011 )2 sayısı, işaretsiz olarakdüşünülürse, 131’e eşittir. Ancak işaretli bir sayı olduğu düşünülürse, karşılığı, -125 olacaktır. Konunun pekişmesi açısından aşağıdaki örneklere göz atabilirsiniz:
* ( 1011 1011 )2 = -69 (Sayı işaretliyse)
( 1011 1011 )2 = 187 (Sayı işaretsizse)
* ( 1100 1101 )2 = -51 (Sayı işaretliyse)
( 1100 1101 )2 = 205 (Sayı işaretsizse)
* ( 0110 1101 )2 = 109 (Sayı işaretliyse)
( 0110 1101 )2 = 109 (Sayı işaretsizse)
Negatif bir sayının 2’lik tabandaki karşılığını bulmak için, önce (i)sayıyı pozitif olarak ikilik tabanda yazarız. Daha sonra, (ii) ikiliktabanda yazılmış sayının 1 yazan rakamları 0, 0 yazan rakamları 1’e çevrilir.Son olarak (iii) çıkan sayıya, 1 eklenir. Bu size istediğiniz sayınınikilik tabanındaki eşini verecektir. Şimdi bir uygulama yapalım ve -7 sayını ikilik tabana çevirmeye çalışalım:
i ) -7 ==> ( 7 )10 = ( 0000 0111 )2
ii ) ( 0000 0111 ) ==> ( 1111 1000 )
iii ) ( 1111 1000 ) + 1 = ( 1111 1001 )==> ( -7 )10 = ( 1111 1001 )2
Bit Bazında ( Bitwise ) Operatörler
Bit bazında operatörlerin, İngilizce’deki karşılığı Bitwise Operators( yani Bit bit Operatörler ) olarak geçmektedir. Bit bazında operatörler, ikilik sayı tabanında yapabileceğimiz işlemleri temsil eder. Kullanılan operatörleri aşağıdainceleyeceğiz.
AND ( & ) Operatörü
AND operatörü, kendisine verilen iki değişkenin bütün bitleri 1’e eşitolduğu takdirde, geriye 1 döndürür. Aksi halde -yani en ufak bir fark varsa- 0 değeri dönmektedir.
p q p&q
0 0 0
0 1 0
1 0 0
1 1 1
x 0 0
x 1 x
Şimdi, AND ( & ) operatörünü 25 ve 14 sayılarını karşılaştırmak için kullanalım:
25 ==> ( 0001 1001 )2
14 ==> ( 0000 1110 )2
&
—————————-
8 ==> ( 0000 1000)2
OR ( | ) Operatörü
İki değişkenden herhangi biri 1 içeriyorsa, geriye 1 döner. Eğer her ikisi de 0içeriyorsa, geriye 0 dönmektedir.
p q p|q
0 0 0
0 1 1
1 0 1
1 1 1
x 0 x
x 1 1
Daha önce kullandığımız 25 ve 14 sayıları üzerinde OR ( | ) işlemi kullanalım:
25 ==> ( 0001 1001 )2
14 ==> ( 0000 1110 )2
|
—————————-
31 ==> ( 0001 1111)2
ÖNEMLİ NOT: Bit bazında kullanılan, AND( & ) ve OR ( | )operatörleri, koşullu ifadelerde kullanılan, AND( && ) ve OR( || ) ifadelerinden farklıdır. Şayet, & veya | bir koşullu ifade gibikullanmaya kalkarsanız, işlem yine yapılacaktır. Ancak bunu yapmanız tavsiyeedilmez. İlerki konularımızda neden uygun olmadığı, short-circuit ile ilgilibilgi verilirken açıklanacaktır.
NOT ( ~ ) Operatörü
NOT ( ~ ) Operatörü, kendisine verilen sayıya ait bit’leri tam tersineçevirir. Yani 0 gördüğü yeri 1; 1 gördüğü yeri 0 yapar.
p ~p
0 1
1 0
25 ==> ( 0001 1001 )2
~
—————————-
230 ==> ( 1110 0110 )2
XOR ( ^ ) Operatörü
XOR ( Exclusive OR ) Operatörü, sadece ve sadecekarşılaştırma yapılan bitlerden biri, 1 değerine sahipse, geriye 1 döndürür.Eğer karşılaştırma yapılan bit’lerden her ikisi de 0 veya 1’se, o zaman sonuç0 olarak çıkar.
p q p^q
0 0 0
0 1 1
1 0 1
1 1 0
x 0 x
x 1 ~x
25 ==> ( 0001 1001 )2
14 ==> ( 0000 1110 )2
^
—————————-
23 ==> ( 0001 0111 )2
Kaydırma ( Shift ) Operatörleri
Kaydırma operatörleri, özellikle Assembly ile uğraşanlara tanıdık gelecektir.Bunları kullanarak son derece hızlı çarpma ve bölme yapılabilir. C’deyse benzeramaçlarla kullanmanız elbette mümkündür. İki çeşit kaydırma operatörü vardır:
i) Sola Kaydırma – Shift Left ( << )
ii) Sağa Kaydırma – Shift Right ( >> )
Her iki durumda da genel kullanım şekli aşağıdaki gibidir:
[ Tam Sayı ][ Operatör ][ Kaydırma Adım Sayısı ]
Aşağıdaki örnek, sola kaydırma operatörü kullanılarak yapılan bir işlemigöstermektedir. x değişkeni, 10 tabanında 22 sayısını tutmaktadır. 2 adım solakaydırılması sonucu, sayı 88 olmuş ve y’ye atanmıştır.
x = ( 0001 0110 )2 ==> 22
y = x << 2
y = ( 0101 1000 )2 ==> 88
Operatör Öncelikleri
Hatırlarsanız, aritmetik işlemlerde önceliklerin olduğunu ve örneğin çarpmanın,toplamadan daha önce yapılacağını anlatmıştık. Benzer bir durum, operatörleriçinde geçerlidir. Altta bulunan tabloda, hangi operatörün dahaönce işleme alındığını bulabilirsiniz:
OPERATÖR ÖNCELİK SIRASI
DÜŞÜK | ^ & << >> + – * / % ! ~ – ++ — ( ) YÜKSEK
Aşağıda bulunan tablo, ilişkisel ve mantıksal operatörlerde ki önceliksırasını göstermektedir:
İLİŞKİSEL ve MANTIKSAL OPERATÖR ÖNCELİK SIRASI
DÜŞÜK || && == != > >= < <= ! YÜKSEK
Yukardaki tablolarda, aynı hücrede olan operatörlerin işlem öncelikleriaynıdır. Önce hangisi yazılmışsa, ilk olarak o dikkate alınır. Ama bunun dışındatanınan bir işlem önceliği bulunmamaktadır.
Aşağıdaki örnek, operatör önceliklerini pekiştirmek açısından incelenebilir:
7 & 13 ^ 11 % 4 * 2 << 14 / 4
==> 7 & 13 ^ 6 << 3
==> 5 ^ 48 = 53
Şimdi de benzer bir örneği, C programı yazarak yapalım:
#include<stdio.h>
int main( void )
{
printf( “İşlem Sonucu: %d\n”, 117 & 11 << 2 * 3 );
return 0;
}
Yukardaki program, 64 sonucunu vermektedir. Programı çalıştırdığınızda,ikilik düzeyde işlemler yapılacak ve 64 cevabına ulaşılacaktır. Siz dehesaplayarak, aynı yanıtı bulabilirsiniz.
Bir sonraki dersimizde, konu anlatımı olmayacak. Onun yerine bol bol örnek yapıp, şimdiye kadar işlediğimiz konuların üzerinden geçeceğiz. Görüşmek üzere…