Ne arasındaki farktır decimal
, float
ve double
.NET?
Birisi bunlardan ne zaman yararlanır?
Ne arasındaki farktır decimal
, float
ve double
.NET?
Birisi bunlardan ne zaman yararlanır?
Yanıtlar:
float
ve double
edilir kayan ikili noktası türleri . Başka bir deyişle, böyle bir sayıyı temsil ederler:
10001.10010110011
İkili sayı ve ikili noktanın konumu değer içinde kodlanır.
decimal
Bir olan kayan ondalık noktası türü . Başka bir deyişle, böyle bir sayıyı temsil ederler:
12345.65789
Yine, ondalık noktanın numarası ve konumu değer içinde kodlanır - decimal
sabit nokta türü yerine hala kayan nokta türü yapan da budur .
Dikkat edilmesi gereken önemli nokta, insanların tamsayı olmayanları ondalık formda temsil etmek için kullanılması ve ondalık gösterimlerde kesin sonuçlar beklemesidir; ondalık sayıların tümü ikili kayan noktalı - 0,1 - tam olarak gösterilemez, bu nedenle ikili kayan nokta değeri kullanırsanız, 0,1'e yaklaşırsınız. Kayan ondalık noktasını kullanırken de yaklaşık tahminler alırsınız - örneğin, 1'e 3 ayırmanın sonucu tam olarak temsil edilemez.
Ne zaman kullanılacağı konusunda:
"Doğal olarak kesin ondalık sayılar" olan değerler için kullanılması iyidir decimal
. Bu genellikle insanlar tarafından icat edilen herhangi bir kavram için uygundur: finansal değerler en açık örnektir, ancak başkaları da vardır. Örneğin dalgıçlara veya buz patencilerine verilen puanı düşünün.
Gerçekten ölçülemez nitelikte daha eserler olan değerler için tam Neyse, float
/ double
daha uygundur. Örneğin, bilimsel veriler genellikle bu formda temsil edilir. Burada, orijinal değerlerle başlamak için "ondalık olarak doğru" olmayacaktır, bu nedenle beklenen sonuçların "ondalık doğruluğunu" sürdürmesi önemli değildir. Kayan ikili nokta türleriyle çalışmak ondalık sayılara göre çok daha hızlıdır.
float
/ double
genellikle sayıları temsil etmez 101.101110
, normalde 1101010 * 2^(01010010)
bir üs olarak temsil edilir - bir üs
float
, bir C # diğer anahtar kelime ve bir .Net türü değil şaşırdım . bu System.Single
.. single
ve double
kayan ikili nokta tipleridir.
Hassasiyet ana farktır.
Şamandıra - 7 basamak (32 bit)
Çift -15-16 basamak (64 bit)
Ondalık -28-29 anlamlı basamak (128 bit)
Ondalık sayılar çok daha yüksek bir hassasiyete sahiptir ve genellikle yüksek derecede doğruluk gerektiren finansal uygulamalarda kullanılır. Ondalık sayılar bir çift / şamandıradan çok daha yavaştır (bazı testlerde 20X kata kadar).
Ondalık Sayılar ve Şamandıralar / Çiftler oyuncu kadrosu olmadan karşılaştırılamazken; Ondalık basamaklar ayrıca kodlama veya sondaki sıfırlara da izin verir.
float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);
Sonuç:
float: 0.3333333
double: 0.333333333333333
decimal: 0.3333333333333333333333333333
0.1
- bu gerçek dünyada nadiren böyle! Herhangi bir sonlu depolama formatı, sonsuz sayıda olası değeri sınırlı sayıda bit deseni ile sınırlar. Örneğin, float
birleşecek 0.1
ve 0.1 + 1e-8
, decimal
birleşecek 0.1
ve 0.1 + 1e-29
. Elbette, belirli bir aralıkta belirli değerler sıfır doğruluk kaybıyla herhangi bir biçimde gösterilebilir (örn. float
Sıfır doğruluk kaybıyla 1.6e7'ye kadar herhangi bir tamsayıyı saklayabilir) - ancak bu yine de sonsuz doğruluk değildir .
0.1
olduğu değil özel bir değer ! Kılan tek şey 0.1
"daha iyi" 0.10000001
çünkü insanoğlu tabanın 10. Ve hatta olduğu gibi float
sizinle iki değeri başlatmak eğer değeri, 0.1
aynı şekilde, her ikisi de aynı değeri olacaktır . Sadece bu değer tam olarak 0.1
olmayacak - tam olarak bir olarak gösterilebilecek en yakın değer olacaktır0.1
float
. Tabii ki, ikili şamandıralarla, (1.0 / 10) * 10 != 1.0
ancak ondalık şamandıralarla (1.0 / 3) * 3 != 1.0
da. Her ikisi de mükemmel bir şekilde kesin değildir.
double a = 0.1; double b = 0.1;
o zaman a == b
gerçek olacak . Sadece bu a
ve b
her ikisi de tam olarak eşit olmayacak 0.1
. C # 'da yaparsanız, decimal a = 1.0m / 3.0m; decimal b = 1.0m / 3.0m;
o a == b
zaman da doğru olacaktır. Ama bu durumda, ne bir a
ne de b
irade tam olarak eşit 1/3
- yapacaklar hem eşit 0.3333...
. Her iki durumda da, temsil nedeniyle bir miktar doğruluk kaybolur. İnatla bunun decimal
"sonsuz" hassasiyete sahip olduğunu söylüyorsunuz , bu yanlıştır .
Ondalık yapı kesinlikle, yuvarlamaya nispeten toleranssız olan doğruluk gerektiren finansal hesaplamalara yöneliktir. Bununla birlikte, ondalık sayılar bilimsel uygulamalar için yeterli değildir, ancak birkaç nedenden dolayı:
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
Diğer cevaplarda ve yorumlarda zaten cevaplanmış tonlarca iyi (ve bazı kötü) bilgileri tekrarlamayacağım, ancak takip sorunuza bir ipucu ile cevap vereceğim:
Birisi bunlardan ne zaman yararlanır?
Sayılan değerler için ondalık kullanma
Ölçülen değerler için şamandıra / çift kullanın
Bazı örnekler:
para (para sayıyor muyuz veya para mı ölçüyoruz?)
mesafe (mesafeyi sayar mıyız veya mesafeyi ölçer miyiz? *)
puanlar (puanları sayar mıyız veya puanları mı ölçeriz?)
Her zaman para sayıyoruz ve asla ölçmemeliyiz. Genellikle mesafeyi ölçeriz. Sık sık skorları sayıyoruz.
* Bazı durumlarda, nominal mesafe dediğim şeyi gerçekten de 'saymak' isteyebiliriz. Örneğin, şehirlere mesafeler gösteren ülke işaretleriyle uğraşıyoruz ve bu mesafelerin asla birden fazla ondalık basamağa (xxx.x km) sahip olmadığını biliyoruz.
float
7 basamak hassasiyet
double
yaklaşık 15 basamak hassasiyete sahiptir
decimal
yaklaşık 28 basamak hassasiyete sahiptir
Daha iyi bir doğruluk istiyorsanız, şamandıra yerine çift kullanın. Modern CPU'larda her iki veri türü de neredeyse aynı performansa sahiptir. Şamandıra kullanmanın tek yararı, daha az yer kaplamasıdır. Pratik olarak sadece birçoğunuz varsa önemlidir.
Bunun ilginç olduğunu gördüm. Her Bilgisayar Bilimcisinin Kayan Nokta Aritmetiği Hakkında Bilmesi Gerekenler
double
32 bitten daha büyük bir tamsayı türünün olmadığı ve double
53 bitlik bir tamsayı türü (örn. bir kaç kuruş veya bir kuruşun yüzde biri gibi). Günümüzde bu tür şeyler için fazla bir kullanım yok, ancak birçok dil, 64-bit (veya bazı durumlarda 32-bit!) Tamsayı matematiğini kazanmadan çok önce çift kesinlikli kayar nokta değerleri kullanma yeteneği kazandı.
Real
IIRC birim hassasiyeti ile 1.8E + 19'a kadar değerleri temsil edebilen Turbo-87 idi . Bir muhasebe uygulamasının, Real
daha fazla sayıda peni temsil etmek için kullanması daha
double
9E15'e kadar birim doğruluğu olan bir tamsayı türüne sahip olmamaları çok yaygındı . Kullanılabilir en büyük tamsayı türünden daha büyük olan tam sayıları depolamak gerekirse double
, özellikle işlemcilerin 16x16-> 32 ya da. ..
Kimse bundan bahsetmedi
Varsayılan ayarlarda, Floats (System.Single) ve çiftler (System.Double) hiçbir zaman taşma denetimi kullanmazken, Ondalık (System.Decimal) her zaman taşma denetimi kullanır.
Demek istediğim
decimal myNumber = decimal.MaxValue;
myNumber += 1;
OverflowException özel durumunu atar .
Ancak bunlar şunları yapmaz:
float myNumber = float.MaxValue;
myNumber += 1;
&
double myNumber = double.MaxValue;
myNumber += 1;
float.MaxValue+1 == float.MaxValue
, aynen decimal.MaxValue+0.1D == decimal.MaxValue
. Belki de böyle bir şey mi demek istediniz float.MaxValue*2
?
System.Decimal
Bu bütün birimlerini ayırt edemez hale gelir hemen önce bir istisna atar ancak bir uygulama çok geç olabilir mesela dolar ve sent, başa olması gerekiyordu eğer.
decimal
sıfıra bölmeye çalışırsanız (CS0020) başarısız olur ve aynı şey integral değişmez değerler için de geçerlidir. Ancak, çalışma zamanı ondalık değeri sıfıra bölünürse, derleme hatası değil bir istisna alırsınız.
Tamsayılar, belirtildiği gibi tam sayılardır. Noktayı .7, .42 ve .007 gibi bir şey saklayamazlar. Tam sayı olmayan sayıları depolamanız gerekiyorsa, farklı bir değişken türüne ihtiyacınız vardır. Çift tip veya şamandıra tipini kullanabilirsiniz. Tam olarak aynı şekilde yukarı değişkenlerin bu tür ayarlayın: yerine kelime kullanmanın int
, yazarken double
veya float
. Bunun gibi:
float myFloat;
double myDouble;
( float
"kayan nokta" nın kısaltmasıdır ve sonunda nokta olan bir sayı anlamına gelir.)
İkisi arasındaki fark, tutabilecekleri sayıların büyüklüğündedir. İçin float
, numaranızda en fazla 7 hane olabilir. İçin double
s, 16 haneye kadar olabilir. Daha kesin olmak gerekirse, resmi boyut şöyledir:
float: 1.5 × 10^-45 to 3.4 × 10^38
double: 5.0 × 10^-324 to 1.7 × 10^308
float
32 bitlik bir sayıdır ve double
64 bitlik bir sayıdır.
Koda ulaşmak için yeni düğmenizi çift tıklayın. Düğme kodunuza aşağıdaki üç satırı ekleyin:
double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());
Programınızı durdurun ve kodlama penceresine dönün. Bu satırı değiştirin:
myDouble = 0.007;
myDouble = 12345678.1234567;
Programınızı çalıştırın ve çift düğmeye tıklayın. Mesaj kutusu numarayı doğru görüntüler. Yine de sonuna başka bir sayı ekleyin, C # tekrar yukarı veya aşağı yuvarlanır. Ahlaki doğruluk istiyorsanız, yuvarlamaya dikkat edin!
decimal
aslında ondalık biçimde saklanır (taban 2'nin aksine; bu nedenle, iki sayısal sistem arasındaki dönüşüm nedeniyle rakamları kaybetmez veya yuvarlamaz); ayrıca decimal
NaN, -0, ∞ veya -∞ gibi özel değerler kavramına sahip değildir.
Bu benim için ilginç bir iş parçacığı oldu, çünkü bugün, decimal
a'dan daha az hassasiyete sahip olmakla ilgili kötü bir hata yaşadık float
.
C # kodumuzda, bir Excel e-tablosundan sayısal değerleri okuyor, bunları a dönüştürüyoruz decimal
ve sonra decimal
bir SQL Server veritabanına kaydetmek için bunu bir Hizmete geri gönderiyoruz .
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
decimal value = 0;
Decimal.TryParse(cellValue.ToString(), out value);
}
Şimdi, neredeyse tüm Excel değerlerimiz için, bu güzel çalıştı. Ancak bazı, çok küçük Excel değerleri decimal.TryParse
için değeri tamamen kaybetti. Böyle bir örnek
hücreDeğer = 0.00006317592
Decimal.TryParse (cellValue.ToString (), çıkış değeri); // 0 döndürür
Çözüm, tuhaf bir şekilde, Excel değerlerini bir double
ilke ve ardından bir decimal
:
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
double valueDouble = 0;
double.TryParse(cellValue.ToString(), out valueDouble);
decimal value = (decimal) valueDouble;
…
}
A'dan double
daha az hassas olmasına rağmen decimal
, bu aslında küçük sayıların hala tanınmasını sağlamıştır. Bazı nedenlerden ötürü, double.TryParse
aslında bu kadar küçük sayıları alabildi, oysa decimal.TryParse
onları sıfıra ayarladı.
Garip. Çok tuhaf.
decimal.Parse("0.00006317592")
çalışıyor - başka bir şey daha var. - Muhtemelen bilimsel gösterim?
Hafıza ve performansın kritik olduğu oyunlar ve gömülü sistemler gibi uygulamalar için, şamandıra genellikle daha hızlı ve bir çiftin yarısı kadar büyüklükte olduğundan sayısal seçimdir. Tamsayılar tercih edilen silahtı, ancak kayan nokta performansı modern işlemcilerde tamsayıyı geçti. Ondalık doğru çıktı!
Ondalık, Çift ve Kayan değişken türleri değerleri saklama biçimlerinden farklıdır. Kesinlik, şamandıranın tek duyarlıklı (32 bit) kayar nokta veri türü, çiftin çift duyarlıklı (64 bit) kayar nokta veri türü ve ondalık sayı ise 128 bit kayan nokta veri türü olduğu ana farktır.
Şamandıra - 32 bit (7 basamak)
Çift - 64 bit (15-16 basamak)
Ondalık - 128 bit (28-29 anlamlı basamak)
Hakkında daha fazla ... Ondalık, Kayan Nokta ve Çift arasındaki fark
Tüm bu türlerle ilgili sorun, belirli bir belirsizliğin geçmesi ve bu sorunun aşağıdaki örnekte olduğu gibi küçük ondalık sayılarla oluşabilmesidir.
Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1
If fMean - fDelta < fLimit Then
bLower = True
Else
bLower = False
End If
Soru: bLower değişkeni hangi değeri içerir?
Cevap: 32 bitlik bir makinede bLower TRUE içerir !!!
Double'i Ondalık olarak değiştirirsem, bLower iyi yanıt olan FALSE içerir.
Çifte, sorun şu ki 1.1'den daha düşük olan fMean-fDelta = 1.09999999999.
Dikkat: Bence aynı sayı diğer sayılar için de var olabilir, çünkü Ondalık daha yüksek hassasiyete sahip bir çifttir ve hassasiyet her zaman bir sınıra sahiptir.
Aslında, Double, Float ve Decimal COBOL'da İKİLİ ondalık sayıya karşılık gelir!
COBOL içinde uygulanan diğer sayısal türlerin .Net'te bulunmaması üzücüdür. COBOL bilmeyenler için COBOL'de sayısal türden sonra var
BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte)
Basit bir deyişle:
/==========================================================================================
Type Bits Have up to Approximate Range
/==========================================================================================
float 32 7 digits -3.4 × 10 ^ (38) to +3.4 × 10 ^ (38)
double 64 15-16 digits ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
decimal 128 28-29 significant digits ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
/==========================================================================================
Daha okuyabilir burada , Float , Double ve ondalık ' .
Decimal
finansal uygulamalar için uygundur ve bu arasında karar verirken kullanmak ana kriter var Decimal
ve Double
. Double
Örneğin hassasiyetin bilimsel uygulamalar için yeterli olmaması nadirdir (ve sınırlı aralığı nedeniyle bilimsel uygulamalar için Decimal
genellikle uygun değildir ).
Bunların her biri arasındaki ana fark hassasiyettir.
float
bir 32-bit
sayı, double
bir 64-bit
sayı ve decimal
bir 128-bit
sayıdır.
Ondalık 128 bit (28-29 anlamlı basamak) Finansal uygulamalarda, ondalık türleri kullanmak daha iyidir, çünkü size yüksek düzeyde doğruluk sağlar ve yuvarlama hatalarından kaçınmak kolaydır Hassasiyet gerektiren tamsayı olmayan matematik için ondalık kullanın (örn. para ve para birimi)
Çift 64 bit (15-16 basamaklı) Çift Türler, para işlemek dışında gerçek değerler için muhtemelen en çok kullanılan veri türüdür. En kesin cevabın gerekli olmadığı tamsayı olmayan matematik için double kullanın.
Kayan 32 bit (7 basamaklı) Çoğunlukla grafik kütüphanelerinde kullanılır, çünkü işlem gücü için çok yüksek talepler, ayrıca yuvarlama hatalarına dayanabilecek durumlar da kullanılır.
Decimals
a'dan çok daha yavaştır double/float
.
Decimals
ve Floats/Doubles
bir oysa döküm olmadan karşılaştırılamaz Floats
ve Doubles
kutu.
Decimals
ayrıca kodlamaya veya sondaki sıfırlara da izin verir.
değerleri şöyle belirtmelisiniz:
Decimal dec = 12M/6;
Double dbl = 11D/6;
float fl = 15F/6;
ve sonuçları kontrol edin.
Float - 4
Double - 8
Decimal - 12