İçeriğe geç
academia.sh

Ders 04 / 16

Kayan Noktalı Sayılar

Gerçel değerlerin sonlu bitle temsili, IEEE 754 alan yapısı ve kesinlik kaybının kaynağı.

İçindekiler

Tam sayılarda temsil ya vardır ya yoktur: sekiz bitte 200200 yazılabilir, 300300 yazılamaz. Kesirli sayılarda durum daha rahatsız edicidir. 00 ile 11 arasında sonsuz sayıda gerçel sayı vardır; sonlu bir bit kümesi bunların yalnızca sonlu bir alt kümesini tutabilir. Geri kalanı temsil edilemez ve en yakın temsil edilebilir değere yuvarlanır.

Bu dersin sorusu, bu alt kümenin nasıl seçildiğidir. Seçim, hesaplama sonuçlarına doğrudan yansır: bu dersin sonunda 0,1+0,20{,}1 + 0{,}2 toplamının neden tam olarak 0,30{,}3 etmediği, bir tuhaflık değil beklenen davranış olarak görünecektir.

Sabit Nokta ve Sınırı

Akla ilk gelen çözüm, ondalık ayracı sabit bir konuma yerleştirmektir. Sekiz bitin üstü tam kısma, altı kesir kısmına ayrılabilir; kesir bitlerinin konum değerleri 212^{-1}, 222^{-2}, 232^{-3} diye sürer:

0101,10102=4+1+0,5+0,125=5,625\texttt{0101{,}1010}_2 = 4 + 1 + 0{,}5 + 0{,}125 = 5{,}625

Bu sabit noktalı (fixed-point) gösterimdir ve belirli alanlarda hâlâ kullanılır. Sorunu, aralık ile çözünürlüğün birbirine kilitlenmesidir: kesire ayrılan her bit, temsil edilebilen en büyük sayıyı yarıya indirir. Bir hesaplamada hem gezegenler arası uzaklıkları hem de atom yarıçaplarını taşımak gerekiyorsa, sabit bir ayraç konumu iki ihtiyacın ikisini birden karşılayamaz.

Bilimsel Gösterimin İkilik Karşılığı

Çözüm, ayracın konumunu değerin kendisiyle birlikte saklamaktır. Bilimsel gösterimde 6,022×10236{,}022 \times 10^{23} yazıldığında iki bilgi taşınır: anlamlı rakamlar ve büyüklük mertebesi. İkilik karşılığı aynı yapıdadır:

(1)s×1,m×2e(-1)^{s} \times 1{,}m \times 2^{e}

Burada ss işaret, mm kesir kısmı (mantis), ee ise üstür. Ayraç, üs değiştikçe “kayar” — gösterimin adı buradan gelir.

Bir ayrıntı bit tasarrufu sağlar: sıfır dışındaki her sayı, üs uygun seçilerek 1,1{,}\dots biçiminde yazılabilir. Baştaki 11 her zaman var olduğuna göre saklanmasına gerek yoktur; donanım onu örtük kabul eder. Böylece mantis alanının tamamı kesir kısmına ayrılır ve bir bit bedavaya kazanılır.

IEEE 754 Alan Yapısı

Kayan noktalı gösterimin bit düzeyindeki ayrıntıları IEEE 754 standardında tanımlıdır. İki yaygın genişlik:

Biçim Toplam İşaret Üs Mantis Üs kayması
binary32 (tek kesinlik) 32 bit 1 8 23 127
binary64 (çift kesinlik) 64 bit 1 11 52 1023

Üs alanı işaretli sayı olarak değil, kaydırmalı (biased) saklanır: alanda duran değerden sabit bir kayma çıkarılarak gerçek üs bulunur. binary32’de alanda 130130 duruyorsa gerçek üs 130127=3130 - 127 = 3’tür. Bu düzenlemenin nedeni sıralamadır: kaydırmalı üs sayesinde iki pozitif kayan noktalı sayı, bit örüntüleri işaretsiz tam sayı gibi karşılaştırılarak sıralanabilir.

Üs alanının iki uç değeri özel anlamlara ayrılmıştır:

  • Tüm bitler 00: değer sıfır (mantis de sıfırsa) veya normal altı (subnormal) sayı. Normal altı sayılar, sıfıra çok yakın bölgede örtük 11 kuralından vazgeçerek çözünürlüğü sürdürür.
  • Tüm bitler 11: mantis sıfırsa sonsuz, sıfır değilse sayı değil (NaN).

Sonsuz ve NaN, taşan veya tanımsız işlemlerin sonucunu programı durdurmadan taşır. 1/01/0 sonsuz, 0/00/0 ise NaN verir. NaN’ın ayırt edici özelliği, kendisine bile eşit olmamasıdır; bu, bir değerin NaN olup olmadığını sınamanın standart yoludur.

Ortak Örneğin Kayan Noktalı Yorumu

Kursun ortak örneği 0x41424344, binary32 olarak yorumlandığında alanlara şöyle ayrılır:

0s 10000010u¨s alanı 10000100100001101000100mantis\underbrace{0}_{s}\ \underbrace{1000\,0010}_{\text{üs alanı}}\ \underbrace{100\,0010\,0100\,0011\,0100\,0100}_{\text{mantis}}

  • İşaret biti 00 olduğundan sayı pozitiftir.
  • Üs alanı 100000102=1301000\,0010_2 = 130; gerçek üs 130127=3130 - 127 = 3.
  • Mantis alanı 4.342.5964.342.596; kesir değeri 4.342.596/223=0,5176777839660644531254.342.596 / 2^{23} = 0{,}517677783966064453125. Örtük 11 eklenince anlamlı kısım 1,5176777839660644531251{,}517677783966064453125 olur.

Değer:

1,517677783966064453125×23=12,1414222717285156251{,}517677783966064453125 \times 2^{3} = 12{,}141422271728515625

Aynı 32 bit, işaretsiz tam sayı olarak 1.094.861.6361.094.861.636, kayan noktalı sayı olarak 12,14142227172851562512{,}141422271728515625 okunur. Bit örüntüsü değişmemiştir; değişen, ona uygulanan yorum kuralıdır. Bir programlama dilinde değişkenin tipi, tam olarak bu kuralı seçmek içindir.

Hangi Sayılar Tam Temsil Edilir

Mantis ikilik bir kesirdir. Dolayısıyla tam temsil edilen değerler, paydası ikinin kuvveti olan kesirlerdir: 0,50{,}5, 0,250{,}25, 0,750{,}75, 3,1253{,}125 gibi. Bu tür sayılara ikilik kesir (dyadic rational) denir.

0,10{,}1 bunlardan değildir. Onluk sistemde tek basamakla yazılan bu sayı, ikilik sistemde devirli bir açılım verir:

0,110=0,0001100110011001120{,}1_{10} = 0{,}0001100110011\overline{0011}\dots_2

Devirli açılım sonlu mantise sığmaz; en yakın temsil edilebilir değere yuvarlanır. binary64’te saklanan değer 0,10{,}1 değil, ona çok yakın başka bir sayıdır. Aynısı 0,20{,}2 ve 0,30{,}3 için de geçerlidir.

Bu, dilin veya donanımın kusuru değildir: 1/31/3 sayısının onluk sistemde sonlu basamakla yazılamaması ne kadar doğalsa, 1/101/10 sayısının ikilik sistemde sonlu bitle yazılamaması da o kadar doğaldır. Değişen, hangi paydaların “şanslı” olduğudur.

Toplamanın Sonucu

Yuvarlanmış iki değer toplandığında sonuç da yuvarlanır ve hatalar birikir:

print(0.1 + 0.2)              # 0.30000000000000004
print(0.1 + 0.2 == 0.3)       # False
print(f"{0.1:.20f}")          # 0.10000000000000000555

import math
print(math.isclose(0.1 + 0.2, 0.3))   # True

import struct
(deger,) = struct.unpack(">f", bytes.fromhex("41424344"))
print(deger)                  # 12.141422271728516

0.1 + 0.2 == 0.3 karşılaştırmasının yanlış sonuç vermesi, bir hata değil temsilin doğrudan sonucudur. Kayan noktalı değerler bu nedenle eşitlikle karşılaştırılmaz; aradaki farkın kabul edilebilir bir eşiğin altında olup olmadığına bakılır. isclose gibi işlevler bu karşılaştırmayı göreli ve mutlak tolerans ile birlikte yapar.

struct modülü, dört baytlık ham veriyi belirtilen biçimde yorumlar; ">f" biçim dizgisi “büyük uçlu, tek kesinlikli kayan noktalı” demektir. Buradaki uç sırası belirtiminin ne anlama geldiği, bu konunun son dersinin konusudur.

Kesinlik Sınırı

Mantis genişliği, taşınabilen anlamlı basamak sayısını belirler. binary32 yaklaşık 7 anlamlı ondalık basamak, binary64 yaklaşık 15–17 basamak taşır. Bu sınırın iki pratik sonucu vardır.

Birincisi: çok büyük ve çok küçük değerler toplandığında küçük olan kaybolabilir. Büyük bir sayıya, mantisin çözünürlüğünün altında kalan bir değer eklendiğinde sonuç değişmez.

İkincisi: hesap sırası sonucu etkiler. Kayan noktalı toplama birleşme özelliği taşımaz — (a+b)+c(a + b) + c ile a+(b+c)a + (b + c) farklı sonuç verebilir. Bu, tam sayılardan alışılan cebirsel özelliklerin burada geçerli olmadığı anlamına gelir ve sayısal yöntemlerin ayrı bir disiplin olmasının nedenlerinden biridir.

Para tutarları gibi ondalık kesinliğin sözleşme gereği olduğu alanlarda kayan noktalı tipler kullanılmaz; onluk tabanlı sabit kesinlikli tipler ya da tam sayı olarak saklanan en küçük birim (örneğin kuruş) tercih edilir.

Özet

  • Sonlu bit, gerçel sayıların yalnızca sonlu bir alt kümesini tutar; geri kalanı en yakın temsil edilebilir değere yuvarlanır.
  • Kayan noktalı gösterim değeri (1)s×1,m×2e(-1)^s \times 1{,}m \times 2^{e} biçiminde saklar; baştaki 11 örtüktür ve bir bit kazandırır.
  • IEEE 754 binary32’de alanlar 1 / 8 / 23 bittir ve üs 127127 kaydırmasıyla saklanır; üs alanının uç değerleri sıfır, normal altı sayı, sonsuz ve NaN için ayrılmıştır.
  • Tam temsil edilen kesirler, paydası ikinin kuvveti olanlardır; 0,10{,}1 bunlardan değildir.
  • Kayan noktalı değerler eşitlikle değil, tolerans ile karşılaştırılır; toplama birleşme özelliği taşımaz.
  • Aynı 0x41424344 örüntüsü tam sayı olarak 1.094.861.6361.094.861.636, binary32 olarak 12,14142227172851562512{,}141422271728515625 okunur.

Sonraki Adım

Buraya kadar bit örüntüleri hep bir bütün olarak yorumlandı. Oysa programlar sık sık tek tek bitlerle çalışır: bir bayrağı açmak, bir alanı ayıklamak, bir değeri iki katına çıkarmak. Sonraki ders, bunları yapan bit düzeyi işleçleri tanımlayacak; önceki derslerde kullanılan >> ve & işleçleri de orada gerekçesine kavuşacak.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat