Java'da Parasal Değerleri Gösterme [kapalı]


94

Java'da parasal değerleri temsil etmek için BigDecimal'in önerilen en iyi uygulama olduğunu anlıyorum. Ne kullaniyorsun? Bunun yerine kullanmayı tercih ettiğiniz daha iyi bir kütüphane var mı?



1
Kopyalayabileceğiniz ve genişletebileceğiniz bir Para Birimi sınıfı: java-articles.info/articles/?p=254
Gilbert Le Blanc

Ayrıca referans JSR-354 uygulanmasının bkz github.com/JavaMoney/jsr354-ri
yendi

Yanıtlar:


81

BigDecimaltüm yol. Bazı insanların kendi sınıflarını Cashveya Moneypara birimiyle nakit değeri içeren sınıfları yarattığını duydum , ancak cilt altında hala bir BigDecimal, muhtemelen BigDecimal.ROUND_HALF_EVENyuvarlama ile.

Düzenleme: Don'un cevabında belirttiği gibi, timeandmoney gibi açık kaynaklı projeler var ve geliştiricilerin tekerleği yeniden icat etmek zorunda kalmalarını önlemeye çalıştıkları için onları alkışlarken, bir ön alfa kitaplığına yeterince güvenmiyorum. bir üretim ortamında. Eğer kaputun altında kazmak yanında, eğer görürsünüz kullandıkları BigDecimalda .


4
+1. Bir para birimi tüketen bir konteyner sınıfı da eklemeye karar verdik. Bu, tablolarda parasal değerleri işlerken kullanışlıdır.
Daniel Hiller

1
evet, bu oldukça yaygın bir yaklaşım ve çok mantıklı. Buna bir uyarı, Japon Yeni ile uğraşmanız gerektiğinde, çünkü sent gibi küçük bir para birimi değerine sahip değiller, bu yüzden kendi yuvarlama kurallarına ihtiyacı var.
34'te dokuzlu

3
@ninesided, kendi yanıtınızı atmanın neden kötü bir cevap olduğuna dair harika bir örnek verir. "Bu arada, $ CURRENCY_X için çalışmıyor." Bu, diğer birçok para birimi için de işe yaramadığının iyi bir işaretidir.
James Moore

1
@JamesMoore "Kendini yuvarlamak" ın kötü bir yaklaşım olduğuna katılmıyorum, sadece seçtiğin yaklaşımın olası sınırlamalarının farkında olmalısın, dolayısıyla bundan bahsetmemin nedeni. Para birimi başına farklı yuvarlama kuralları uygulamak önemsizdir, ancak sisteminizin yalnızca USD veya EUR cinsinden işlem yapması gerekiyorsa, çok fazla mühendislik yapmanız gerekmez.
dokuzlu

1
Stackoverflow.com/questions/5134237/… sitesine bir göz atın, BigDecimal'in neden bir sorun olmasının tek bir nedeni var. Gezegen çapında muhasebe sadece özel durumlardan oluşan bir bataklıktır ve hepsini BigDecimal kilidinin altına süpürmeye çalışmak işe yaramaz.
James Moore



8

Daha önce karşılaştığım kullanışlı bir kütüphane Joda-Money kütüphanesi. Uygulamalarından biri gerçekten BigDecimal'e dayanmaktadır. Para birimleri için ISO-4217 spesifikasyonunu temel alır ve özelleştirilmiş bir para birimi listesini (CVS aracılığıyla yüklenir) destekleyebilir.

Bu kitaplık, değişiklik gerektiğinde hızlı bir şekilde geçilebilecek az sayıda dosyaya sahiptir. Joda-Money, Apache 2.0 lisansı altında yayınlanmaktadır.


7

Sadece dolar ve sent kullanıyorsanız, uzun (2 ondalık basamak ile ofset) kullanırım. Daha fazla ayrıntıya ihtiyacınız varsa, büyük ondalık en iyi yol olabilir.

Her iki durumda da, muhtemelen sınıfı doğru biçimi kullanan bir .toString () 'e sahip olacak şekilde ve ortaya çıkabilecek diğer yöntemleri koymak için bir yer olarak genişletebilirim (Uzun bir süre için, çarpma ve bölme, ondalık sayı değilse ayarlandı)

Ayrıca, kendi sınıfınızı ve arabiriminizi tanımlamayı kullanırsanız, uygulamayı istediğiniz zaman değiştirebilirsiniz.


2
Dikkat edin, uzun bile olsa ABD Federal Borçunu Sent cinsinden tutmak için çok kısa olabilir ... şimdi değilse o zaman birkaç yıl sonra.
Ingo

3
Katılıyorum - muazzam sayıda dolar (veya eğer Yen cinsinden parayı takip ediyorsanız) BigDecimal kullanmalısınız - ama o zaman bile bunun için bir konteyner sınıfı kullanmayı ciddi olarak düşünürdüm. Bence çoğu programlama karmaşıklığı, koleksiyonlar ve içsel türler etrafında küçük, basit sınıfları tanımlamayan insanlardan kaynaklanıyor.
Bill K

3

BigDecimal veya başka bir sabit nokta temsili genellikle para için gerekli olan şeydir.

Kayan nokta ( Double, Float) gösterimleri ve hesaplamaları kesin değildir ve hatalı sonuçlara yol açar.


7
Kesin olarak, BigDecimal de kesin değildir; günlük hayatta alıştığımız ondalık yuvarlamaya daha iyi karşılık gelir ve yuvarlama modlarını belirlemenize olanak tanır.
Michael Borgwardt

1
@Michael Borgwardt BigDecimal, açık bir ölçek belirtilmesi açısından IEEE FP'den farklıdır. Tüm işlemler kesin olmasa da, bu, bir dizi işlemin ve davranışın her zaman kesin ve ölçeğin sabit olmasını sağlarken, IEEE FP ölçeği değerle birlikte azalır.

1
Bunun parayla ne alakası var? Dünyanın dört bir yanındaki muhasebe kuruluşlarının genellikle kendi para birimlerinde nasıl matematik yaptığınız konusunda çok özel gereksinimleri vardır. BigDecimal bu standartların her birine tam olarak uyuyor mu? Önümüzdeki yıl, bu standartlar değiştiğinde bunu yapacak mı? Ve BigDecimal, para birimleri için yararlı yuvarlama kuralları belirlemeye bile yaklaşmıyor.
James Moore

2

Zaman ve parayla uğraşırken çok dikkatli olmalısın.

Parayla çalışırken umarım herkes şamandıra veya duble kullanmamayı bilmelidir.

Ama BigDecimal hakkında emin değilim.

Çoğu durumda, sadece int veya long cinsinden sentleri takip ederseniz, iyi olacaksınız. Bu şekilde asla ondalık basamakla uğraşmazsınız.

Yalnızca yazdırdığınızda dolar görüntülersiniz. Her zaman tamsayı kullanarak dahili sentlerle çalışın. Bölmeniz gerekiyorsa veya Math.abs () kullanmanız gerekiyorsa, bu zor olabilir.

Bununla birlikte, yarım sent, hatta bir sentin yüzde biri umurunda olabilir. Bunu yapmanın iyi bir yolunun ne olduğunu bilmiyorum. Sadece binde sent ile uğraşmanız ve uzun bir süre kullanmanız gerekebilir. Ya da belki BigDecimal kullanmaya zorlanacaksınız

Bunun üzerine çok daha fazla okuma yapardım, ancak parayı temsil etmek için float veya double kullanmaktan bahsetmeye başlayan herkesi görmezden gelin. Sadece bela istiyorlar.

Tavsiyemin tam olmadığını hissediyorum, bu yüzden lütfen daha fazlasını yazın. Tehlikeli tiplerle uğraşıyorsun!


2
BigDecimal'i kullanmak için neden "zorunlu" olmanız gerekiyor? Neden emin değilsin? Açıkça yuvarlama modlarını belirlemenize izin verdiği için sentlerle çalışmaktan açıkça üstündür.
Michael Borgwardt

1
@MichaelBorgwardt: evet, para birimleri için ihtiyacınız olan yuvarlama modlarının küçük bir alt kümesini belirlemenize izin verir. Yani? (İpucu: Yuvarlama para birimlerine genellikle ulusal muhasebe kuruluşları tarafından karar verilir. Garip özel durumlarda karıştırmaktan son derece mutlular. BigDecimal yuvarlamanın tamamen olmasının birçok eğlenceli nedeninden sadece biri için stackoverflow.com/questions/5134237/… adresine bakın. burada işe yaramaz.)
James Moore

@James: Tam olarak nasıl "işe yaramaz"? BigDecimal ile bu özel durumları uygulamak başka bir şeyden daha zor olabilir mi?
Michael Borgwardt

1
Tamam, tamamen yararsız, çok güçlü. Para birimini özetleyen karmaşık sınıfta, BigDecimal'in yuvarlama kuralları muhtemelen bazı özel durumlarda para birimi yuvarlamanın gerçekleştiği yolların bir alt kümesini oluşturmak için yararlıdır. Ancak genel durum, para birimleri için yuvarlama kurallarının zamanla değişebilecek mekanizmalar gerektirmesidir (çünkü kuralları insan muhasebe kurumları oluşturur ve bunları değiştirmekte özgürdür). Soru Euro (ya da gelecek ay Euro'nun yerini alacak ne olursa olsun ...) ya da 2011'de dolar ile ilgili değil, para birimi ile ilgili, bu yüzden pek çok çirkin karmaşıklıkla uğraşmanız gerekiyor.
James Moore

2

Para sınıfı oluşturmak, gidilecek yoldur. Altında BigDecimal (veya hatta bir int) kullanma. Ardından, yuvarlama kuralını tanımlamak için Currency sınıfını kullanma.

Maalesef operatörün aşırı yüklenmesi olmadan Java, bu tür temel türlerin oluşturulmasını oldukça rahatsız eder.


2

Daha iyi bir kütüphane, zaman ve para var . IMO, bu 2 kavramı temsil etmek için JDK tarafından sağlanan kitaplıklardan çok daha üstündür.


3
Bu cevap üç yıl önce yayınlandı. Bugün, timeandmoney projesi bu bağlantıya göre hala alfa öncesi.
James Moore

1
@JamesMoore İyi çağrı. Cevap şu anda 7 yaşında ve proje hala istikrarlı değil.
Navin

1

Kesinlikle BigDecimal değil. Yuvarlama ve sunum için endişelenmeniz gereken çok sayıda özel kural vardır.

Martin Fowler, para birimi tutarlarını temsil etmek için özel bir Para sınıfının uygulanmasını önerir ve bu aynı zamanda para birimi dönüştürme kurallarını da uygular.


6
ve Money sınıfının temelindeki veri türü? BigDecimal.
ninesided

1
Bu doğru değil. Tamsayı'yı para sınıfında kullanabilirsiniz, bu Martin'in yaptığı şeydir. Bunu birçok kez yaptım.
egervari

Yine de tavsiye doğrudur; Para içeren hesaplamalar, zamanla değişen geniş bir özel durum bataklığıdır. BigDecimal, çözümün küçük bir parçası olarak yararlı olabilir, ancak kesinlikle genel değildir.
James Moore

1

Hey, işte BigDecimal hakkında çok ilginç bir makale ve neden bazen çiftler yerine kullanıldığına dair açıklayıcı bir örnek. BigDecimal Eğitimi .


0

Nihayetinde bir para birimi değeri görüntülerken DecimalFormat sınıfını kullanabilirsiniz. Yerelleştirme desteği sağlar ve oldukça genişletilebilir.


0

BigDecimal'i, yukarıda bahsettiğim gibi bir para birimi olan Money sınıfına dahil ederdim. Önemli olan, aşırı miktarda birim testi yapmanız ve özellikle farklı para birimleriyle çalışmanızdır. Ayrıca, bir dizi alan uygun bir kurucu veya aynı şeyi yapan bir fabrika yöntemi eklerseniz, testlerinizi şöyle bir şey yazabilmeniz için iyi bir fikirdir:

   assertEquals(Money.create("100.0 USD").add("10 GBP"),Money.create("116 USD"));

0

Her zaman kısıtlamalar ve ayrıntılar vardır. Aşağıdaki makalede ana hatlarıyla belirtilen ince sorunları takdir etmek için yeterli deneyime sahip olmayan herkes, gerçek dünyadaki finansal verilerle uğraşmadan önce ciddi şekilde yeniden düşünmelidir:

http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money

BigDecimal, bulmacanın tek doğru temsili veya tek parçası değildir. Belirli koşullar altında, tamsayı olarak depolanan sentlerle desteklenen bir Money sınıfı kullanmak yeterli olabilir ve BigDecimal'den çok daha hızlı olacaktır. Evet, bu, para birimi ve limit miktarları olarak dolar kullanımını ima eder, ancak bu tür kısıtlamalar birçok kullanım durumu için mükemmel şekilde kabul edilebilir ve tüm para birimlerinin yuvarlama ve alt para birimleri için özel durumları vardır, bu nedenle "evrensel" bir çözüm yoktur.


1
Bu, gerçek bir cevap yerine başka bir gönderiye yapılan bir yorum gibi görünüyor. Aynı zamanda aşırı derecede sinir bozucu. Lütfen gelecekte daha medeni olmaya çalışın.
Slater Victoroff
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.