Çö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.
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ı?
Double yerine float kullanmayı dene.
 
Artı -3 Eksi
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
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?
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ı -3 Eksi
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.
 
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

Yeni konular

Geri
Yukarı