Kayan Nokta Sayıları (Floating Point Numbers)

Yazan : Şadi Evren ŞEKER

Bilgisayar yapılarında ondalıklı sayıları ( floatingpoint numbers ) iki farklı bilginin tutulması ile gösterilebilir:

mantis x kök üst

yukarıda verilen formüle göre bir ondalıklı sayıyı önce bir ondalık çarpan sonra da bir kök’ün verilen üstü ile çarpımı olarak göstermek mümkündür.

Örneğin ikilik tabanda 1101.11 küsurlu sayısını ele alalım (“.” işaretinden sonraki kısım küsurudu). Bu sayıyı göstermek için öncelikle bütün sayıyı önce 4 hane ilerleterek (kaydırarak, float) sayının tamamını küsurlu hale getirelim:

.110111

Yukarıdaki bu sayının orjinal değerini taşıyan gösterimi

.110111 x 2 4

olmalıdır çünkü orjinal sayının 4 hane kaydırılmış halidir. Dolayısıyla sayımızı aşağıdaki iki tamsayıyı tutarak göstermek mümkündür:

mantisa (mantissa) : 110111

üst (exponent) :  0100 (onluk tabandaki 4′ün karşılığı)

Merve Hanımın soruları üzerine aşağıdaki kısmı eklemenin gerekli olduğu anlaşılmıştır:

Kayan noktaların gösterimi

Konuyu örnek bir sayı üzerinden anlamaya çalışalım. Örneğin sayımız 123.321 olsun.

Sayımızın tam kısmı 123′tür küsurat kısmı aşağıdaki şekilde yazılabilir:

3*10 -1 + 2*10 -2 + 1*10 -3

Bu düşünce, bizim alıştığımız onluk sistemdeki yaklaşımdır. Bu sayının ikilik tabana nasıl çevrileceği ile ilgili olarak “ Ondalık sayıların taban dönüşümü” başlıklı yazıyı okuyabilirsiniz.

Ayrıca yukarıdaki sayımızı bilimsel gösterimde aşağıdaki şekilde yazabiliriz:

1.23321 * 10 2

Tek hassasiyetli (single precision) kayan nokta sayısı, 32 bitlik bir paket olarak düşünülebilir. Bu yapı aşağıdaki tabloda temsil edilmiştir:

X
XXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXX
Yön

Sign
1 bit

Üst

Exponent
8 bit

Kök

Mantissa
23 bit

 

Yön biti (sign bit)

Bu bit 1 olduğu zaman, sayımız – değerdedir. Şayet 0 veya artı değerde bir sayı ise, bu bit 0 olur.

Üst Biti (Exponent Bit)

Yukarıdaki örnekte gösterilen bilimsel yazıma göre, sayının üst değeri bu alanda tutulur. Buna göre bir sayının 2′nin kaçıncı kuvveti ile çarpılabileceğini gösterir.

Burada dikkat edilecek bir husus, üst değerinin de eksi olabileceğidir. Örneğin sayımız 0.000123 ise, bu sayının bilimsel gösterimi : 1.23 * 10 -4 olacaktır.

Bu durumda 8 bitlik alanın ilk biti yön bilgisi tutmaktadır. O halde geriye kalan 7 bit, üst bilgisi tutabilir. Buradan çıkan sonuç, sayımızın en fazla 127. üstüne kadar olan değerin tutulabileceğidir (2 7 =128 olduğunu ve bu bilginin ilk değerinin 0 için ayrıldığını dolayısıyla, sayımızın 0 – 127 arasında olacağını hatırlayınız).

Kök biti (mantissa bit)

23 bit alan kaplayan kısımdır. Bu alana bazı durumlarda belirgin anlamına gelen (significand) ismi de verilir. Bu kısım bilimsel gösterimin kök kısmıdır. Örneğin 1.23 * 10 -4 sayısı için kök kısmı 123 olacaktır.

Örnek sayı

Yukarıdaki alanların, bir örnek sayı için nasıl gösterildiğine bakalım:

21,25 sayısını çevirmeye çalışalım. Öncelikle bu sayının ikilik tabandaki karşılığını bulalım:

10101.01

Bu sayıyı, bilimsel gösterime çevirelim:

21,25 = 2,125 * 10 -1 = 2125 * 10 -3

Ayrıca son bir bilgi : (2125) 10 = (1000010001101) 2

Şimdi bu sayının hafızadaki tutuluşuna bakalım:

Yön bitimiz, sayımız pozitif olduğu için 0 olacak.

Üst bitlerimiz, sayının üstü -3 olduğu için 100000011 olacak. Buradaki son iki bit 3 değerini, baştaki bit ise yönün eksi olduğunu göstermektedir.

Geriye kalan alan ise kök değerini tutacaktır.

(21) 10 = (10101) 2 olduğuna göre,sayımız aşağıdaki şekilde gösterilebilir:

0
10000011 01010100000000000000000
Yön

Sign
1 bit

Üst

Exponent
8 bit

Kök

Mantissa
23 bit

 

Sonuç olarak sayımız:

01000001101010100000000000000000

şeklinde bulunmuş olunur.

Çift hassasiyet ve tek hassasiyet ( double precision , single precision)

Yukarıdaki yazı, tek hassasiyet dikkate alınarak hazırlanmıştır. Bunun anlamı sistemin 32 bit olmasıdır. Sistem 64 bit olabilir. Bu durumda çift hassasiyetten bahsedilmelidir. İki sistem arasındaki fark, aşağıdaki şekildedir:

1 bit yön biti (sign bit)
8 bit üst değeridir (exponent)
23 bit kök değeridir (mantissa)

64bitlik bir sistemde ise durum aşağıdaki şekildedir:
1 bit yön bitidir (sign bit)
11 bit üst değeridir (exponent)
52 bit kök değeridir (mantissa)

Kayan nokta gösteriminden Onluk sisteme çevirim

Bu çevirimi anlamak için bir örnek üzerinden konuyu anlatalım.

Çevirmek istediğimiz sayı, 0xC0B40000 olsun. Bu sayı onaltılık tabandadır (hexadecimal) ve aşağıdaki şekilde ikilik tabana (binary) çevirilebilir:

Onaltılık C 0 B 4 0 0 0 0
İkilik
1100
0000
1011
0100
0000
0000
0000
0000

Yukarıdaki çevirimden çıkan ve tek hassasiyetli (single precision) gösterim aşağıda verilmiştir:

1
10000001
01101000000000000000000

Demek ki sayımız eksi bir değermiş (en baştaki yön biti 1 olduğu için) ve ayrıca üstü de eksi imiş (yön bitini tutan grup 1 ile başladığı için).

Gelelim kök kısmının (mantissa) dönüşümüne.

Kök kısmımızdaki değer, 01101 olarak bulunuyor. Bu değeri yukarıdaki bilgiler ile birleştirirsek aslında sayımız aşağıdaki şekildedir:

-1.01101 * 2 2

Artık problemimiz bu sayıyı onluk tabanda göstermektir. Sayının her basamağının üst değerini yazalım:

-(2 0 + 2 -2 + 2 -3 + 2 -5) * 2 2 = -(2 2 + 2 0 + 2 -1 + 2 -3)

değerleri hesaplayalım:

-(4 + 1 + .5 + 0.125) = -5.625

Bu yazıyı beğendiyseniz, başkalarının da ilgisini çekebilirsiniz:


561 views

10 responses to “Kayan Nokta Sayıları (Floating Point Numbers)”
  1. Zeynep Şadoglu says:

    İyiydi teşekkürler

  2. Merve says:

    Hocam merhaba, öncelikle bilgilendirmeniz için teşekkürler. Ben de bir yerde görmüştüm merak ettim. Mesela;
    -2 sayısının binary, hexadecimal, truncation, precision value of the real number olarak sırasıyla şu şekilde göstermiş :
    11000000 10000000 00000000 00000000
    C0 80 00 00
    -2,0
    -2,0 +-0,0

    C programlama dilinde bunlar için kullanabileceğimiz fonksiyonlar mevcut mudur, yoksa nasıl bu şekilde gösteriliyor? Yanıtlarsanız çok sevinirim.

  3. ANSI C için, ne yazık ki bu şekilde çevirim yapan hazır fonksiyonlar yok. Ancak bazı özellikler belki işinize yarar.

    Örneğin, herhangi bir sayıyı %x ile bastırırsanız hexadecimal (onaltılık) karşılığını alırsınız.

    #include <stdio.h>
    
    int main(){
        int c = 123;
        printf("sayi :%d",c);
        printf(" onaltili: %x",c);
        return 0;
    }
    ~
    

    Yukarıdaki kodun çktısı aşağıdaki şekildedir:

    sayi :123 onaltili: 7b

    Truncate işlemi için (kesme), tam sayılardan faydalanabilirsiniz:

    #include <stdio.h>
    #include <math.h>
    int main(){
        float c = -2.3433;
        printf("sayi :%f",c);
        int tamkisim = c*100;
        c = (float)tamkisim / 100;
        printf(" kesilmis :  %f",c);
        return 0;
    }
    ~
    

    Yukarıdaki kodun çıktısı :

    sayi :-2.343300 kesilmis : -2.340000

    Yukarıdaki kodda, float sayının 100 mislinin (virgülün iki kaydırılmış halinin) tam sayıya çevrilerek (ki bu anda virgülden sonra kalan diğer değerler kaybolur) ardından float sayıya geri döndürülmesi söz konusudur.

    C dili için yukarıdaki durum söz konusu iken JAVA gibi gelişmiş dillerde bu isteklerinizi yapan fonksiyonlar bulunmaktadır.

    Örneğin aşağıdaki kod bu çevirimleri yapmaktadır:

    public class deneme{
        public static void main(String args[]){
            int x = 123;
            System.out.println(Integer.toBinaryString(x));
            System.out.println(Integer.toHexString(x));
        }
    }
    

    Yukarıdaki kodun çıktısı aşağıdaki şekildedir:

    1111011
    7b

    Gelelim float sayıların çevirimine. Ne yazık ki JAVA’da bulunan Float, kılıf sınıfının (wrapping class) doğrudan bir dönüşüm fonksiyonu yok. Yani Intger.toBinaryString() der gibi Float.toBinaryString() diyemeyiz. Bu problemi çözmek için biraz daha uğraşmamız gerekiyor:

    public class deneme{
        public static void main(String args[]){
            Float f = 123.456f;
            System.out.println(f);
            System.out.println(Integer.toHexString(Float.floatToIntBits(f)));
        }
    }
    

    Çıktısı :
    123.456
    42f6e979

    Görüldüğü üzere istenilen amaca göre elimizdeki dilin özelliklerini kullanmamız gerekiyor. Genelde floating numbers (kayan nokta sayıları) yakın bir değer tutarlar ve tam değer bulundurmazlar. Bu anlamda, programlama dilleri açısından çoğu zaman problem oluştururlar. Ancak istenilen amaç tam olarak belirlendikten sonra o dildeki özelliklere göre kullanılabilirler.

    başarılar

  4. Merve says:

    Cevabınız için çok teşekkürler hocam. Peki sayının 32 bitlik gösterimi için nasıl bir yol izlemeliyiz? Kolay gelsin.

  5. sayılar zaten tanımlı olduğu işletim sistemi / derleyici (compiler) ortamına bağımlıdır. Siz normalde bir değişken tanımladığınızda o ortamdaki değerlere göre tanımlanır.

    Öncelikle 32 bit olması durumunda sayıda nasıl değişiklik oluyor ona bakalım.

    Örneğin sayımız 2 olsun. Bu sayının ikilik tabandaki karşılığı 10 olarak gösterilir. Ancak 32 bit olan bir sistemde 0000 0000 0000 0000 0000 0000 0000 0010 şeklinde görülür. Yani sistem 32 bittir.

    Biraz daha ilerleyerek -2 sayısını irdeleyelim. Bu sayı yönlü bir sayıdır (signed). Dolayısıyla 32 bitlik yerin bir biti yöne ayrılır. Bu bit en baştaki bittir:

    1000 0000 0000 0000 0000 0000 0000 0010

    Görüldüğü üzere sadece baştaki bit eksi sayılar için 1 diğer sayılar için (0 ve artı sayılar) 0′dır.

    Ancak sayı eksi sayı olarak tanımlanıp sonra on altılık sisteme çevirilirse, baştaki değerin yön biti olduğu bilgisi kaybedilerek baştaki değer de çevirilir.

    Bu durumu aşağıdaki kod üzerinden anlamaya çalışalım:

    #include <stdio.h>
    #include <math.h>
    int main(){
        int c = -2;
        printf("sayi :%d",c);
        printf(" onaltilik :  %x",c);
        return 0;
    }
    

    Yukarıdaki kodun çıktısı aşağıdaki şekildedir:

    sayi :-2 onaltilik : fffffffe

    Görüldüğü üzere, sayı -2′dir ve 0 – 2 işleminin sonucu olarak düşünülür. bu durumda -1 değeri, 32 bitlik sistemdeki en büyük değer olan ff ff ff ff ile aynıdır. -2 değeri ise bu sayının bir eksiği olan ff ff ff fe olarak gösterilmiştir.

    Yukarıdaki bu durum elbette 32 bit için geçerlidir.

    Kısacası 32 bit bir sistemde ilk bit yönlü sayılar için yön bitidir (sign bit) ve sonraki bitler (geri kalan 31 bit) veri için kullanılır.

    Gelelim kayan nokta sayılarına (float numbers). 32 bit bir sistemde durum aşağıdaki şekildedir:

    1 bit yön biti (sign bit)
    8 bit üst değeridir (exponent)
    23 bit kök değeridir (mantissa)

    64bitlik bir sistemde ise durum aşağıdaki şekildedir:
    1 bit yön bitidir (sign bit)
    11 bit üst değeridir (exponent)
    52 bit kök değeridir (mantissa)

    Aslında bütün bunlardan sonra yazıya tekrar baktım da, sanırım yazıda bu konuları anlatmakta fayda var. Birazdan yazıya gerekli eklemeleri yapıp konunun daha iyi anlatıldığı bir örnek veririm.

    başarılar

  6. Ecem says:

    Hocam verdiğiniz bilgiler çok faydalı, teşekkür ederim öncelikle. Merak ettiğim iki floating point sayısı üzerinde (32 bitlik gösterimde) dört işlem (toplama, çıkarma, çarpma, bölme) nasıl gerçekleştirilebilir? Yanıtlarsanız çok sevinirim. Kolay gelsin.

  7. gokhan.taskin says:

    yuvarla float , kacbasamak)
    Virgülden sonra kaç basamak yuvarlamak istiyorsak o kadar yuvarlayan fonksiyonu tasarlamak istiyorum hocam .

    ORNEK Yuvarla(3.454556,4)

    yardımcı olursanız sevinirim tesekkurler

  8. Basit bir müsvette kodu (pseudo code) aşağıdaki şekilde yazabilirsiniz:

    float yuvarla(float a, int b){
      int carpan = 10;
      for (int i = 0;i< b;i++)
         carpan *= 10;
      int tam = a*carpan;
      a = (float)tam / (float)carpan;
      return a;
    }
    

    Başarılar

  9. baris says:

    merhaba 8 lik tabandaki 44,44 sayisini nasil 4 luk tabana cevirebiliriz…

Leave a Reply


* 7 = yirmi sekiz

Benzer Yazılar:

Bilgisayar Kavramları üzerinde şu anda okumakta olduğunuz 'Kayan Nokta Sayıları (Floating Point Numbers)' isimli yazı 30 Nov 2008 tarihinde, saat: 13:06 'de Şadi Evren ŞEKER tarafından gönderilmiş, toplam561 defa okunmuştur.

Benzer yazıları Bilgisayar Matematiği, Donanım ( Hardware ), Mantık Devreleri (Logic Circuits), Sistem Programlama (System Programming) kategorilerinden okuyabilirsiniz. Yazar ile irtibat kurmak için email gönderebilirsiniz. Yazıya yorum yapabilir ya da yapılan yorumları RSS 2.0 ile takibe alabilirsiniz.


Category: Bilgisayar Matematiği, Donanım ( Hardware ), Mantık Devreleri (Logic Circuits), Sistem Programlama (System Programming)