जावा में पैसे के लिए आपको किस प्रकार का डेटा इस्तेमाल करना चाहिए?
जावा में पैसे के लिए आपको किस प्रकार का डेटा इस्तेमाल करना चाहिए?
जवाबों:
जावा में Currency
वर्ग है जो आईएसओ 4217 मुद्रा कोड का प्रतिनिधित्व करता है।
BigDecimal
मुद्रा दशमलव मानों का प्रतिनिधित्व करने के लिए सबसे अच्छा प्रकार है।
जोडा मनी ने पैसे का प्रतिनिधित्व करने के लिए एक पुस्तकालय प्रदान किया है।
आप मुद्रा और मुद्रा एपीआई (जेएसआर 354) का उपयोग कर सकते हैं । आप इस API का उपयोग कर सकते हैं, बशर्ते आप अपनी परियोजना में उपयुक्त निर्भरता जोड़ दें।
जावा 8 के लिए, आपके लिए एक निर्भरता के रूप में निम्नलिखित संदर्भ कार्यान्वयन जोड़ें pom.xml
:
<dependency>
<groupId>org.javamoney</groupId>
<artifactId>moneta</artifactId>
<version>1.0</version>
</dependency>
यह निर्भरता javax.money:money-api
एक निर्भरता के रूप में संचरित होगी।
फिर आप एपीआई का उपयोग कर सकते हैं:
package com.example.money;
import static org.junit.Assert.assertThat;
import static org.hamcrest.CoreMatchers.is;
import java.util.Locale;
import javax.money.Monetary;
import javax.money.MonetaryAmount;
import javax.money.MonetaryRounding;
import javax.money.format.MonetaryAmountFormat;
import javax.money.format.MonetaryFormats;
import org.junit.Test;
public class MoneyTest {
@Test
public void testMoneyApi() {
MonetaryAmount eurAmount1 = Monetary.getDefaultAmountFactory().setNumber(1.1111).setCurrency("EUR").create();
MonetaryAmount eurAmount2 = Monetary.getDefaultAmountFactory().setNumber(1.1141).setCurrency("EUR").create();
MonetaryAmount eurAmount3 = eurAmount1.add(eurAmount2);
assertThat(eurAmount3.toString(), is("EUR 2.2252"));
MonetaryRounding defaultRounding = Monetary.getDefaultRounding();
MonetaryAmount eurAmount4 = eurAmount3.with(defaultRounding);
assertThat(eurAmount4.toString(), is("EUR 2.23"));
MonetaryAmountFormat germanFormat = MonetaryFormats.getAmountFormat(Locale.GERMAN);
assertThat(germanFormat.format(eurAmount4), is("EUR 2,23") );
}
}
सबसे छोटा मूल्य संभव का प्रतिनिधित्व करने वाला एक अभिन्न प्रकार। दूसरे शब्दों में आपके कार्यक्रम को डॉलर / यूरो में नहीं, सेंट में सोचना चाहिए।
यह आपको गुई में डॉलर / यूरो में वापस अनुवाद करने से नहीं रोकना चाहिए।
BigDecimal का उपयोग किया जा सकता है, फ्लोट या डबल का उपयोग न करने की अच्छी व्याख्या यहाँ देखी जा सकती है: मुद्रा का प्रतिनिधित्व करने के लिए डबल या फ्लोट का उपयोग क्यों नहीं किया जाता है ?
JSR 354: मुद्रा और मुद्रा एपीआई
JSR 354 धन और मुद्रा के साथ व्यापक गणना का प्रतिनिधित्व, परिवहन और प्रदर्शन के लिए एक एपीआई प्रदान करता है। आप इसे इस लिंक से डाउनलोड कर सकते हैं:
JSR 354: मुद्रा और मुद्रा एपीआई डाउनलोड
विनिर्देशन में निम्नलिखित चीजें शामिल हैं:
- मौद्रिक राशि और मुद्राओं को संभालने के लिए एक एपीआई
- विनिमेय कार्यान्वयन का समर्थन करने के लिए एपीआई
- कार्यान्वयन वर्गों के उदाहरण बनाने के लिए फैक्टरियाँ
- मौद्रिक राशियों की गणना, रूपांतरण और प्रारूपण के लिए कार्यशीलता
- जावा एपीआई मनी और मुद्राओं के साथ काम करने के लिए, जिसे जावा 9 में शामिल करने की योजना है।
- सभी विनिर्देश वर्ग और इंटरफेस javax.money। * पैकेज में स्थित हैं।
जेएसआर 354 का नमूना उदाहरण: मुद्रा और मुद्रा एपीआई:
एक मोनोमाउंट बनाने और कंसोल पर इसे प्रिंट करने का एक उदाहरण इस तरह दिखता है ::
MonetaryAmountFactory<?> amountFactory = Monetary.getDefaultAmountFactory();
MonetaryAmount monetaryAmount = amountFactory.setCurrency(Monetary.getCurrency("EUR")).setNumber(12345.67).create();
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));
संदर्भ कार्यान्वयन API का उपयोग करते समय, आवश्यक कोड बहुत सरल है:
MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmountFormat format = MonetaryFormats.getAmountFormat(Locale.getDefault());
System.out.println(format.format(monetaryAmount));
API मौद्रिक गणना के साथ गणना का भी समर्थन करता है:
MonetaryAmount monetaryAmount = Money.of(12345.67, "EUR");
MonetaryAmount otherMonetaryAmount = monetaryAmount.divide(2).add(Money.of(5, "EUR"));
करेंसी यूनाइट और मोनेटअमाउंट
// getting CurrencyUnits by locale
CurrencyUnit yen = MonetaryCurrencies.getCurrency(Locale.JAPAN);
CurrencyUnit canadianDollar = MonetaryCurrencies.getCurrency(Locale.CANADA);
मोनेटअमाउंट में कई तरीके हैं जो निर्दिष्ट मुद्रा, संख्यात्मक राशि, इसकी परिशुद्धता और अधिक तक पहुंचने की अनुमति देते हैं:
MonetaryAmount monetaryAmount = Money.of(123.45, euro);
CurrencyUnit currency = monetaryAmount.getCurrency();
NumberValue numberValue = monetaryAmount.getNumber();
int intValue = numberValue.intValue(); // 123
double doubleValue = numberValue.doubleValue(); // 123.45
long fractionDenominator = numberValue.getAmountFractionDenominator(); // 100
long fractionNumerator = numberValue.getAmountFractionNumerator(); // 45
int precision = numberValue.getPrecision(); // 5
// NumberValue extends java.lang.Number.
// So we assign numberValue to a variable of type Number
Number number = numberValue;
मौद्रिक राउंडिंग ऑपरेटर का उपयोग करके गोल किया जा सकता है:
CurrencyUnit usd = MonetaryCurrencies.getCurrency("USD");
MonetaryAmount dollars = Money.of(12.34567, usd);
MonetaryOperator roundingOperator = MonetaryRoundings.getRounding(usd);
MonetaryAmount roundedDollars = dollars.with(roundingOperator); // USD 12.35
जब मोनेटअमाउंट के संग्रह के साथ काम करते हैं, तो फ़िल्टरिंग, सॉर्टिंग और ग्रुपिंग के लिए कुछ अच्छी उपयोगिता विधियां उपलब्ध हैं।
List<MonetaryAmount> amounts = new ArrayList<>();
amounts.add(Money.of(2, "EUR"));
amounts.add(Money.of(42, "USD"));
amounts.add(Money.of(7, "USD"));
amounts.add(Money.of(13.37, "JPY"));
amounts.add(Money.of(18, "USD"));
कस्टम मौद्रिक संचालन
// A monetary operator that returns 10% of the input MonetaryAmount
// Implemented using Java 8 Lambdas
MonetaryOperator tenPercentOperator = (MonetaryAmount amount) -> {
BigDecimal baseAmount = amount.getNumber().numberValue(BigDecimal.class);
BigDecimal tenPercent = baseAmount.multiply(new BigDecimal("0.1"));
return Money.of(tenPercent, amount.getCurrency());
};
MonetaryAmount dollars = Money.of(12.34567, "USD");
// apply tenPercentOperator to MonetaryAmount
MonetaryAmount tenPercentDollars = dollars.with(tenPercentOperator); // USD 1.234567
संसाधन:
JSR 354 के साथ जावा में पैसे और मुद्राएं संभालना
जावा 9 मनी और मुद्रा एपीआई (जेएसआर 354) में खोज
इसे भी देखें: JSR 354 - मुद्रा और धन
मौद्रिक मूल्यों का प्रतिनिधित्व करने के लिए आपको बिगडेसिमल का उपयोग करना चाहिए । यह आपको कई प्रकार के राउंडिंग मोड्स का उपयोग करने की अनुमति देता है , और वित्तीय अनुप्रयोगों में, राउंडिंग मोड अक्सर एक कठिन आवश्यकता होती है जो कानून द्वारा भी अनिवार्य हो सकती है।
मै इस्तेमाल करूंगा जोडा मनी का
यह अभी भी संस्करण 0.6 पर है, लेकिन बहुत आशाजनक है
मैंने प्रदर्शन के मामले में बिगडेसीमल के खिलाफ मोनेटा (जावा मुद्रा जेएसआर 354 कार्यान्वयन) की तुलना करने के लिए एक माइक्रोबेनमार्क (जेएमएच) किया है।
हैरानी की बात है कि मोनेटा की तुलना में बिगडेसिमल का प्रदर्शन बेहतर है। मैंने निम्नलिखित मोनेटा विन्यास का उपयोग किया है:
org.javamoney.moneta.Money.defaults.preaches = 19 org.javamoney.moneta.Money.defaults.roundingMode = HALF_UP
package com.despegar.bookedia.money;
import org.javamoney.moneta.FastMoney;
import org.javamoney.moneta.Money;
import org.openjdk.jmh.annotations.*;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.concurrent.TimeUnit;
@Measurement(batchSize = 5000, iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS)
@Warmup(iterations = 2)
@Threads(value = 1)
@Fork(value = 1)
@State(Scope.Benchmark)
@BenchmarkMode(Mode.Throughput)
public class BigDecimalBenchmark {
private static final Money MONEY_BASE = Money.of(1234567.3444, "EUR");
private static final Money MONEY_SUBSTRACT = Money.of(232323, "EUR");
private static final FastMoney FAST_MONEY_SUBSTRACT = FastMoney.of(232323, "EUR");
private static final FastMoney FAST_MONEY_BASE = FastMoney.of(1234567.3444, "EUR");
MathContext mc = new MathContext(10, RoundingMode.HALF_UP);
@Benchmark
public void bigdecimal_string() {
new BigDecimal("1234567.3444").subtract(new BigDecimal("232323")).multiply(new BigDecimal("3.4"), mc).divide(new BigDecimal("5.456"), mc);
}
@Benchmark
public void bigdecimal_valueOf() {
BigDecimal.valueOf(12345673444L, 4).subtract(BigDecimal.valueOf(232323L)).multiply(BigDecimal.valueOf(34, 1), mc).divide(BigDecimal.valueOf(5456, 3), mc);
}
@Benchmark
public void fastmoney() {
FastMoney.of(1234567.3444, "EUR").subtract(FastMoney.of(232323, "EUR")).multiply(3.4).divide(5.456);
}
@Benchmark
public void money() {
Money.of(1234567.3444, "EUR").subtract(Money.of(232323, "EUR")).multiply(3.4).divide(5.456);
}
@Benchmark
public void money_static(){
MONEY_BASE.subtract(MONEY_SUBSTRACT).multiply(3.4).divide(5.456);
}
@Benchmark
public void fastmoney_static() {
FAST_MONEY_BASE.subtract(FAST_MONEY_SUBSTRACT).multiply(3.4).divide(5.456);
}
}
जिसके परिणामस्वरूप
Benchmark Mode Cnt Score Error Units
BigDecimalBenchmark.bigdecimal_string thrpt 10 479.465 ± 26.821 ops/s
BigDecimalBenchmark.bigdecimal_valueOf thrpt 10 1066.754 ± 40.997 ops/s
BigDecimalBenchmark.fastmoney thrpt 10 83.917 ± 4.612 ops/s
BigDecimalBenchmark.fastmoney_static thrpt 10 504.676 ± 21.642 ops/s
BigDecimalBenchmark.money thrpt 10 59.897 ± 3.061 ops/s
BigDecimalBenchmark.money_static thrpt 10 184.767 ± 7.017 ops/s
अगर मुझे कुछ याद आ रहा है तो कृपया मुझे सुधारने के लिए स्वतंत्र महसूस करें
साधारण मामले (एक मुद्रा) के लिए यह पर्याप्त है Integer
/ Long
। सेंट (...) या सौवें / हजारवें सेंट के पैसे रखें (किसी भी सटीक जो आपको निर्धारित विभक्त के साथ चाहिए)
BigDecimal मुद्रा के लिए उपयोग करने के लिए सबसे अच्छा डेटा प्रकार है।
मुद्रा के लिए बहुत सारे कंटेनर हैं, लेकिन वे सभी अंतर्निहित डेटा प्रकार के रूप में BigDecimal का उपयोग करते हैं। आप BigDecimal के साथ गलत नहीं करेंगे, शायद BigDecimal.ROUND_HALF_EVEN गोलाई का उपयोग कर रहे हैं।
मुझे टाइनी टाइप्स का इस्तेमाल करना पसंद है जो या तो एक डबल, बिगडेक्मल को लपेटेगा, या पिछले उत्तरों के रूप में सुझाव देगा। (मैं तब तक एक डबल का उपयोग करूंगा जब तक कि सटीक समस्याएं फसल न लें)।
एक टिनी टाइप आपको सुरक्षा प्रदान करता है ताकि आप दूसरे डबल्स के साथ एक डबल पैसा न दें।