Çözüldü C# double veri türü 15.basamak hassasiyeti

Bu konu çözüldü olarak işaretlenmiştir. Çözülmediğini düşünüyorsanız konuyu rapor edebilirsiniz.

bugzone2.0

Hectopat
Katılım
17 Şubat 2018
Mesajlar
471
Makaleler
1
Çözümler
5
Yer
İzmit/KOCAELİ
Daha fazla  
Cinsiyet
Erkek
Meslek
Jr. Java Back-end Developer
C#:
double deger = 8.123456789123458;
Console.WriteLine("Double Türündeki Değer : {0}",deger);

Yukarıda örneğini vermiş olduğum kodun ekran çıktısında 15. hanede bulunan 8 sayısı 7 olarak çıkıyor.
Aynı sayının son hanesi.
1 ıse 0.
2 ıse 2 (denk)
3 ıse 4.
4 ıse 4 (denk)
5 ıse 5 (denk)
6 ıse 5.
7 ıse 7 (denk)
8 ıse 7.
9 ıse 9 (denk)
Rakamlarına yuvarlanıyor. Aralarında matematiksel bir ilişki kuramadım, kimi sayıda yuvarlama yapıyor kimi sayıda yuvarlama yapmıyor. Yaptığı yuvarlamada bir mantık da göremedim bunun sebebi nedir?
Dipnot: C# double veri türü virgülden sonra 15 haneye kadar duyarlıdır.
Benim sorum 15. hanedeki yuvarlama mantığı. Yuvarlama mantığında 5 altı 0'a 5 ve üzeri 10'a yuvarlanır.
Yine farklı bir şekilde değer verdiğimizde yukarıda bulunan 1 ise 0 yapma durumu değişiyor.
Örneğin;

C#:
double deger = 8.000000000000001;

İlk örnekte 15. hanede 1 rakamını 0 yapan derleyici ikinci örnekte 1 rakamını 2 yapıyor.

Bu konu hakkında bilgi sahibi olan var mı?
 
Çözüm
IEEE standartlari sebebiyle.

C# mantissa boyutunu kac tutuyor bilmiyorum ama, 15. basamaktaki hassasiyet bias sebebiyle her zaman dogru reprezente edilmiyor olabilir.

Bunda bir yanlislik yok.

15. basamaktaki decimal deger, binary olarak 64 bit (mantissa + exponent) ikilisiyle dogru gosterilemiyor, sebep bu. Bias her sayiya gore degisir. Ustteki linkten inceleyebilirsiniz.

"The exponent field needs to represent both positive and negative exponents. To do this, a bias is added to the actual exponent in order to get the stored exponent."

(bias, burada dikkat etmeniz gereken farklilik )

Java'daki BigDecimal'a denk gelen C# class'ini kullanip arbitrary hassasiyet elde edebilirsiniz memory'den feragat ederek.
Bu bir yuvarlama hatası.

Remember that a floating-point number can only approximate a decimal number, and that the precision of a floating-point number determines how accurately that number approximates a decimal number. By default, a Double value contains 15 decimal digits of precision, although a maximum of 17 digits is maintained internally. The precision of a floating-point number has several consequences:

  • Two floating-point numbers that appear equal for a particular precision might not compare equal because their least significant digits are different.
  • A mathematical or comparison operation that uses a floating-point number might not yield the same result if a decimal number is used because the floating-point number might not exactly approximate the decimal number.

Burda İngilizce olarak anlatılmış durum. Çevirmek istemedim, zira bozuluyor:


C#:
double deger_double = 8.123456789123458;
Console.WriteLine("Double  Türündeki Değer : {0}",deger_double);
        
decimal deger_decimal = 8.123456789123458M;
Console.WriteLine("Decimal Türündeki Değer : {0}",deger_decimal);

Arkadaşlar konuya matematiksel net bir cevap dışında bir yorum yapıp bilgi kirliliğine yol açmayalım.

Bilgi kirliliği göremiyorum. Eğer siz görüyorsanız, rapor edebilirsiniz.

@Vavien. gayet mantıklı bir yaklaşımda bulunmuş.
 
Son düzenleme:
Buradaki kimse benim asistanım değil doğru, fakat ben bir soru soruyorum dileyen vakit ayırıp cevaplar dileyen tıklamadan geçer. Olay soruyu okumamandan kaynaklanıyor. Ben 15. basamaktaki hassasiyet sorunundan bahsediyorum sen diyorsun ki float kullan. Float kullansam zaten 15 basamak yazamam akıl var mantık var.
Sayın Aydoğdu lütfen bunu da dikkate alın.

Bence olay değişken türlerinin bellekte ayırdığı alan ile ilgili. Bahsettiğiniz 32 ve 64 bitler de bununla alakalı zaten. Bellekte her bir sayı 4 bitlik bir alan kaplıyor. 64 / 4'de 16 ediyor.
 
Artı -2 Eksi
IEEE standartlari sebebiyle.

C# mantissa boyutunu kac tutuyor bilmiyorum ama, 15. basamaktaki hassasiyet bias sebebiyle her zaman dogru reprezente edilmiyor olabilir.

Bunda bir yanlislik yok.

15. basamaktaki decimal deger, binary olarak 64 bit (mantissa + exponent) ikilisiyle dogru gosterilemiyor, sebep bu. Bias her sayiya gore degisir. Ustteki linkten inceleyebilirsiniz.

"The exponent field needs to represent both positive and negative exponents. To do this, a bias is added to the actual exponent in order to get the stored exponent."

(bias, burada dikkat etmeniz gereken farklilik )

Java'daki BigDecimal'a denk gelen C# class'ini kullanip arbitrary hassasiyet elde edebilirsiniz memory'den feragat ederek.
 
Çözüm
Ieee standartlari sebebiyle.

C# mantissa boyutunu kac tutuyor bilmiyorum ama, 15. basamaktaki hassasiyet bias sebebiyle her zaman dogru reprezente edilmiyor olabilir.

Bunda bir yanlislik yok.

15. basamaktaki decimal deger, binary olarak 64 Bit (mantissa + exponent) ikilisiyle dogru gosterilemiyor, sebep bu. Bias her sayiya gore degisir. Ustteki linkten inceleyebilirsiniz.

"The exponent field needs to represent both positive and negative exponents. To do this, a bias is added to the actual exponent in order to GET the stored exponent."

(Bias, burada dikkat etmeniz gereken farklilik )

Java'daki Bigdecimal'a denk gelen C# Class'ini kullanip arbitrary hassasiyet elde edebilirsiniz Memory'den feragat ederek.

Konu Microsoft tarafından da mantissa + exponent durumuyla açıklanmış.

0.1 * 10 ile 10 kere 0.1 toplamının eşit olmayışı buna örnek.

Konuya kaynaklar ile cevap veren arkadaşlara teşekkür ediyorum. Soruyu okuma zahmetinde bulunduğunuz için ayrıca teşekkürler. Soru çözülmüştür.

Microsoft kaynağı: Microsoft Double Struct
 

Yeni konular

Geri
Yukarı