C # para için kullanılacak en iyi veri türü nedir?


426

C # para için kullanılacak en iyi veri türü nedir?


4
Bu cevaplar bulabilir sonrası yararlı.
ntombela

İşte tüm veri türleri için bir eşleme: docs.microsoft.com/en-us/dotnet/framework/data/adonet/…
JohnLBevan

Ayrıca, veri ek açıklamaları kullanıyorsanız şunları ekleyin using System.ComponentModel.DataAnnotations;... [DataType(DataType.Currency)] msdn.microsoft.com/en-us/library/…
JohnLBevan

Yanıtlar:


422

Ondalık olarak tanımlandığı gibi:

Ondalık anahtar kelime 128 bit veri türünü belirtir. Kayan noktalı türlerle karşılaştırıldığında, ondalık tür daha hassas ve daha küçük bir aralığa sahiptir, bu da onu finansal ve parasal hesaplamalar için uygun hale getirir .

Ondalık bir sayıyı aşağıdaki gibi kullanabilirsiniz:

decimal myMoney = 300.5m;

41
Bu bağlantı hakkında neyin önemli olduğunu açıklamalısınız. Bir yanıt, ek referans veya ayrıntı olarak bir bağlantı ile kendi başına yeterince iyi olmalıdır. Bkz. Stackoverflow.com/help/how-to-answer
TheRubberDuck

2
Bu nedenle, minimum uzunluk cevabı, minimum uzunluk yorumundan daha az karakter olabilir - ilginç! Kısa / özlü cevapla ilgili bir sorunum olduğu için değil, özellikle de daha derin tartışmalara yol açtığı için “derin” olduğunda.
B. Clay Shannon

3
Şaşırtıcı cevap ve soruyu tamamen cevapladığı için daha fazla açıklamaya ihtiyacı olduğunu düşünmüyorum. MSDN belgelerine bağlantı, endişelendiğim kadarıyla bir bonus. Bravo!
trnelson

@Leee Treveil, para neye benziyor (9.0098) Point'ten sonra 4 karakter anlamına geliyor
SAR

114

System.Decimal

Ondalık değer türü, pozitif 79,228,162,514,264,337,593,543,950,335 ile negatif 79,228,162,514,264,337,593,543,950,335 arasında değişen ondalık sayıları temsil eder. Ondalık değer türü, çok sayıda önemli integral ve kesirli basamak gerektiren ve yuvarlama hatası gerektirmeyen finansal hesaplamalar için uygundur. Ondalık tip, yuvarlama ihtiyacını ortadan kaldırmaz. Aksine, yuvarlamadan kaynaklanan hataları en aza indirir.

Neden zneak'in neden çifte kullanılmaması gerektiğine dair bu mükemmel cevaba işaret etmek istiyorum .


68

Kullanım Para desen dan Kurumsal Uygulama Mimarlık Patterns ; tutarı ondalık, para birimini bir enum olarak belirtin.


2
Aslında bunu önerecektim, ama ben bir döviz kuru ("temel para birimi" ile ilgili olarak, genellikle ABD doları [1,00 döviz kuruna sahip olarak ayarladım]) tanımlamak için bir sınıf yapmak.
Thomas Owens

5
Bu konunun gelecekteki ziyaretçileri için (benim gibi), şimdi var: nuget.org/packages/Money ve sallanıyor !
Korijn

Böyle bir türün bir yapı mı yoksa sınıf mı olduğunu merak ediyorum. Ondalık + an (int) bir enum 20 bayt yapar. Param hala yapıda.
nawfal

Bu Moneykülçenin proje sitesi için ölü bir github bağlantısı var yani ... belge yok mu?
George Mauer

Buradaki sorun, kendi uygulamanızı oluşturuyorsanız, aslında nasıl devam edeceğinizi anlamanız gerekir. Ve en popüler ORM'nin (EF) özel veri türleri için hiçbir desteği yoktur. Bu nedenle birinden oldukça basit bir şey olması gereken şeyleri yapmak için yabani otlarda gerçekten derinleşmesi istenir .
George Mauer

25

Ondalık. Eğer çift seçerseniz kendinizi yuvarlama hatalarına açık bırakıyorsunuz


8
@Jess doubleyuvarlama hataları verebilir çünkü kayan nokta tüm sayıları tam olarak temsil edemez (örn. 0.01 kayan noktada tam bir temsili yoktur). DecimalÖte yandan, yok sayıları temsil aynen . ( DecimalDeğişkenlik kayan noktadan daha küçük bir aralığa sahiptir) Kayan nokta size * yanlışlıkla * yuvarlama hataları verebilir (örn. 0.01+0.01 != 0.02). Decimalsize yuvarlama hataları verebilir, ancak yalnızca istediğiniz zaman (örn. Math.Round(0.01+0.02)sıfır döndürür)
Ian Boyd

2
@IanBoyd: "$ 1.57" değeri tam olarak temsil edilebilir (çift) 157. Biri doubleuygun olduğunda ölçeklendirme ve alana özgü yuvarlama kullanır ve dikkatle uygularsa , mükemmel bir şekilde kesin olabilir. Biri yuvarlamada özensiz ise decimal, anlamsal olarak yanlış sonuçlar verebilir (örneğin, bir kişi en yakın kuruşa yuvarlanması gereken, ancak aslında ilk önce onların etrafında olmayan) birden fazla değer eklerse). Bununla ilgili tek iyi şey decimal, ölçeklemenin yerleşik olmasıdır.
supercat

1
@supercat, bu yorum ile ilgili olarak, "eğer bir araya en yakın kuruşa yuvarlanması gerekiyordu ama aslında onların etrafında ilk önce değil birden çok değer ekler", bir şamandıra bunu nasıl çözeceğini görmüyorum. Bu bir kullanıcı hatasıdır ve ondalık IMHO ile ilgisi yoktur. i noktası olsun ama yanlış yerleştirildi hissediyorum, çünkü IanBoyd bunu belirtmek çünkü ... eğer bunu sorarsanız.
sawe


13

Para modeliyle aynı fikirde olun: Ondalık sayılar kullandığınızda para birimleri kullanmak çok zahmetlidir.

Bir Currency sınıfı oluşturursanız, parayla ilgili tüm mantığı, doğru ToString () - yöntemi, değerleri ayrıştırmada daha fazla denetim ve bölümlerde daha iyi denetim de dahil olmak üzere oraya koyabilirsiniz.

Ayrıca, bir Currency sınıfı ile, yanlışlıkla diğer verilerle para karıştırma şansı yoktur.


10

Başka bir seçenek (özellikle kendi sınıfınızı döndürüyorsanız) bir int veya int64 kullanmak ve alt dört basamağı (veya muhtemelen 2) "ondalık noktasının sağı" olarak atamaktır. Yani "kenarlarda" girerken bazı "* 10000" ve çıkışta bazı "/ 10000" gerekir. Bu, Microsoft'un SQL Server tarafından kullanılan depolama mekanizmasıdır, bkz. Http://msdn.microsoft.com/en-au/library/ms179882.aspx

Bunun güzelliği, tüm özetlemenizin (hızlı) tamsayı aritmetiği kullanılarak yapılabilmesidir.


7

decimalParayı temsil etmek için kullandığım çoğu uygulama . Bu, başvurunun asla birden fazla para birimiyle ilgilenmeyeceği varsayımına dayanmaktadır.

Bu varsayım, uygulamanın hiçbir zaman farklı para birimlerine sahip diğer ülkelerde kullanılmayacağı başka bir varsayımı temel alabilir. Bunun yanlış olduğu kanıtlanmış vakalar gördüm.

Şimdi bu varsayım yeni bir şekilde zorlanıyor: Bitcoin gibi yeni para birimleri daha yaygın hale geliyor ve herhangi bir ülkeye özgü değiller. Sadece bir ülkede kullanılan bir uygulamanın yine de birden fazla para birimini desteklemesi gerekebilir.

Bazı insanlar sadece para için bir tür oluşturmanın, hatta kullanmanın "altın kaplama" olduğunu veya bilinen gereksinimlerin ötesinde ekstra karmaşıklık eklediğini söyleyecektir. Kesinlikle katılmıyorum. Bir kavram alan adınızda ne kadar yaygınsa, doğru soyutlamayı kullanmak için makul bir çaba sarf etmek o kadar önemlidir. Karmaşıklığı görmek istiyorsanız, daha önce kullanılan bir uygulamada çalışmayı deneyin decimalve şimdi Currencyher decimalözelliğin yanında ek bir özellik var.

Ön tarafta yanlış soyutlama kullanırsanız, daha sonra değiştirmek yüz kat daha fazla iş olacaktır. Bu, potansiyel olarak mevcut koda kusur getirme anlamına gelir ve en iyi yanı, bu kusurların büyük olasılıkla para, para ile işlemler veya sadece para ile herhangi bir şey içermesidir.

Ondalıktan başka bir şey kullanmak o kadar da zor değil. Google "nuget para türü" ve çok sayıda geliştiricinin bu tür soyutlamaları (ben dahil) oluşturduğunu göreceksiniz. DateTimeA'da bir tarih depolamak yerine kullanmak kadar kolaydır string.


5

Kendi sınıfınızı oluşturun. Bu tuhaf görünüyor, ancak .Net türü farklı para birimlerini karşılamak için yetersiz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.