Kayan Noktalı Sayılar Hakkında

Kayan noktalı sayılarla alakalı bir soru sormak istiyorum. yardımcı olmak isteyenler mesaj atarlarsa sevinirim.

1e+1 == 10 ** 1 # bu ifade True değerini veriyor.
1e+2 == 10 ** 2 # bu ifade de True değerini veriyor.
#
#
1e+22 == 10 ** 22 # bu ifade de True değerini veriyor.
# ancak;
1e+23 == 10 ** 23 # bu ifade False değerini veriyor.

1e+22 bir sınır değer midir diye düşünürken, aklıma 1e+22'den küçük bir sayıyı test etmek geldi.

(1e+21) + 1 == (10 ** 21) + 1 # ancak bu ifade False değerini verdi.

sormak istediğim sorulara gelirsek:

  1. 1e+23 == 10 ** 23 ifadesi neden False değerini verir? Yani 1e+23 sayısı neden int(1e+23) sayısına eşit değildir?

  2. Madem int(1e+21) sayısı 1e+21 sayısına eşit, o halde (1e+21) + 1 == (10 ** 21) + 1 neden False değerini verir?

Not: Mesela sys.maxsize bize 92233720368547758070 sayısını veriyor. Bu sayı 19 haneli bir sayı. Mesela 17 haneli bir sayı için şu sorguyu yapıyorum:

>>> 1e+17 == 10 ** 17
True

>>> 1e+17 == int(1e+17)
True

>>> (1e+17) + 1 == (10 ** 17) + 1
False

# Oysa şöyle yaptığımda `True` değeri yükseltiliyor:
>>> int(1e+17) + 1 == int(10 ** 17) + 1
True
1 Beğeni

1e+23 ile ilgili şöyle bir bildirim yapılmış ve cevap olarak bu bir bug değil denilmiş

https://bugs.python.org/issue26422

https://docs.python.org/3.5/tutorial/floatingpoint.html

1e+23 ifadesini ekrana yazarsak 99999999999999991611392 çıktısı veriyor.

1 Beğeni

Evet 1e+23 ifadesi 99999999999999991611392 yapıyor. Ama mesela şu ifadeler sizce de garip sonuçlar üretmiyor mu?

>>> 1e+17 == 10 ** 17
True

>>> 1e+17 == int(1e+17)
True

>>> (1e+17) + 1 == (10 ** 17) + 1
False

# Oysa şöyle yaptığımda `True` değeri yükseltiliyor:
>>> int(1e+17) + 1 == int(10 ** 17) + 1
True

Yani, örneğin 1e+17, int(1e+17)'ye eşitse, (1e+17) + 1 == (10 ** 17) + 1 işleminin de True değeri vermesi gerekmiyor mu?

1e+17 ifadesine 1 eklediğinizde eklemiyor.

>>> sayi = (1e+17)+1
>>> print("%d"%sayi)
100000000000000000

Ama int yaparsanız ekliyor

>>> sayi = int(1e+17)+1
>>> print("%d"%sayi)
100000000000000001

Sanırım exponent kullanımı ile ilgili biraz daha bilgi edinmemiz gerek

1 Beğeni

Mesela 1e+17 + 9, 1.0000000000000002e+17 sayısını veriyor. Ancak 9'a kadar olan sayılarda sonuç yine 1e+17 oluyor. Bu kayan noktalı sayılar aritmetiği konusunda daha fazla bilgilenmek lazım aslında.

1 Beğeni

Ayrıca şöyle durumlarla da karşılaşabiliyoruz.

>>> sayi = 4234235345435234523452345
>>> int(sayi) == float(sayi)
False
1 Beğeni

Şu sayfa işimize yarayabilir. https://docs.python.org/3/library/decimal.html#decimal-objects

>>> import decimal
>>> sayi = decimal.Decimal(1e+17)
>>> print(sayi+1)
100000000000000001
1 Beğeni

Evet, gösterdiğiniz gibi decimal kütüphanesini kullanarak 1e+17 + 1 sonucunu hesaplayabiliyoruz.

1 Beğeni

float(sayi) ifadesi, sayıyı exponent haline getiriyor. Yine farklı bir formata giriyor

4.2342353454352344e+24
1 Beğeni

Aynen öyle. Daha paylaştığınız sayfayı okumadım o yüzden aklımdaki şu sorular hala güncelliğini koruyor. Neden sayılar farklı formata geçiyorlar? Veya 10 ** 23 ile 1e+23 aynı sayıların farklı ifade ediliş biçimleriyse sonuçlar neden farklılaşıyor? Belki dokümanı okuduktan sonra buna bir cevap bulunabilir.

1 Beğeni

Bunu ben de merak ediyorum :slight_smile:

1 Beğeni

IEEE 754 kayan noktali sayilari baya dertli—duz esitlik ifadesini kullanmamak gerekiyor.
Cogunlukla abs(a-b) <= EPSILON gibi bir kontrol lazim geliyor.

Sebepleri ise burada acmak icin cok uzun (vaktim yok), ama cogu sey sayilarin S M*B^E seklinde tutulmasindan kaynaklaniyor.

Base’i 10 alirsak: 1~10 arasinda alabilecegimiz precision 7 basamak ise (1.234567X == 1.234567Y) 10^50 ile 10^51 arasinda alabilecegimiz precision da ayni, cunku degisen tek sey Exponent.

3 Beğeni

Daha uygun bir zamanda bu konuyla alakalı bildiklerinizi paylaşmanızı rica ediyorum sizden. ^^

Küçük floatların hata vermesi hakkında zaten bilginiz vardır diye tahmin ediyorum:

>>> 0.1  + 0.2
0.30000000000000004

Bu tamamen floatların hafızada saklanma sistemi ile alakalıdır. Aynı sistem büyük sayılarda da hata yapılmasına sebep olur. Güzel olduğunu düşündüğüm ingilizce bir kaynak buldum:

Ayrıca şu videoyu da öneririm:

Konu ile ilgili dökümana da kısa da olsa bir bölüm eklemek istiyorum. Sonuçta

>>> 0.1  + 0.2
0.30000000000000004

Gibi bir durumu ilk defa yaşayan herkes şaşırır :smiley:

aib’in de dediği gibi IEEE 754 standardında -ki bu çoğu yazılım dili tarafından kullanılmaktadır-
işler bu şeklide belirlendiği için böyle çalışıyor. Tabii bunun da sebepleri var. Bu sebeplerden ilk linkte bahsediliyor. Burada da kısa bir türkçe makale var:

2 Beğeni

Paylaştığınız bağlantılar için teşekkür ederim. :+1:

1 Beğeni

Bu video biraz daha anlaşılır yaptı, teşekkürler

1 Beğeni