Çö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.
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
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:
double deger = 8.000000000000001; = 8
double deger = 8.000000000000010 = 8.00000000000001
double deger = 8.000000000000016 = 8.00000000000002

double deger = 8.123456789123458; = 8.12345678912346 bunu verdiğin zaman sondaki yuvarlamayı değiştirir , virgülden sonraki -yuvarlamaya kadar olan- yerlere dokunmaz. Nerede deniyorsun? Vavien'in dediği doğru olabilir.


C# Online Compiler | .NET Fiddle

burayla bi deneme şansın var mı? c# idesi yok iş bilgisayarındayım :D
 
Arkadaşlar konuya matematiksel net bir cevap dışında bir yorum yapıp bilgi kirliliğine yol açmayalım. Muhtemel ve kişisel tahminler dışında net bir bilimsel cevap gerekiyor.
Verdiğim cevap gayet bilimsel. Araştırmaya zahmet etseniz görürdünüz.
 
Arkadaşlar konuya matematiksel net bir cevap dışında bir yorum yapıp bilgi kirliliğine yol açmayalım. Muhtemel ve kişisel tahminler dışında net bir bilimsel cevap gerekiyor.
Madem bu kadar bilimsel cevaplara meraklısınız bir zahmet açıp bu konu hakkındaki yazıları okuyun. İnternet elinizin altında... Burada sizin asistanlarınız yok, siz de profesör değilsiniz.
 
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
 
Double yerine float kullanmayı dene.

Float veri türü 32 Bit, double veri türü 64 Bit bu da yarı yarıya daha az basamak hassasiyeti demek. Bu sebeple float değil decimal kullanmak sorunu çözer.
Fakat ortada sorun değil soru var. Alternatif veri tiplerini ben de biliyorum, sorum şu double veri türünde 15. basamakta bulunan bu hassasiyet probleminin mantıklı açıklaması nedir?
 
Artı -1 Eksi
Madem bu kadar bilimsel cevaplara meraklısınız bir zahmet açıp bu konu hakkındaki yazıları okuyun. İnternet elinizin altında... Burada sizin asistanlarınız yok, siz de profesör değilsiniz.

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.

Verdiğim cevap gayet bilimsel. Araştırmaya zahmet etseniz görürdünüz.

Verdiğiniz cevap bilimsel değil, bilimsel makalelerde muhtemelen gibi kelimeler kullanılmaz.
Konu elbette ondalıklı sayıların tutulması ile ilgili, fakat double veri tipinin son hanesinde olan bu anlamsız yuvarlamanın sebebini soruyorum, muhtelemen cevabından ziyade beklediğim bilimsel bir cevaptı. Benim gibi bu soruyu sorup Technopat üzerinden okumak isteyen insanlara eziyet ediyorsunuz böyle yanıtlarla.
Varsa net cevabınız söyleyin, yoksa takibe alın konuyu ya da bir başka konuya gidin.
Sorduğuma soracağıma pişman ettiniz, teşekkür ediyorum.

Double deger = 8.000000000000001; = 8.
Double deger = 8.000000000000010 = 8.00000000000001.
Double deger = 8.000000000000016 = 8.00000000000002.

Double deger = 8.123456789123458; = 8.12345678912346 bunu verdiğin zaman sondaki yuvarlamayı değiştirir, virgülden sonraki -yuvarlamaya kadar olan- yerlere dokunmaz. Nerede deniyorsun? Vavien'in dediği doğru olabilir.

C# Online Compiler | .NET Fiddle

Burayla bir deneme şansın var mı? C# IDE'si yok iş bilgisayarındayım :D.

Linkteki sitenin derleyicisi de aynı sonuçları veriyor. Deneme yaptığım yer Visual Studio 2019.
 
Artı -1 Eksi

Geri
Yukarı