long を使用して独自の通貨クラスを作成しようとしていましたが、BigDecimal
代わりに使用する必要があるようです。誰かが私が始めるのを手伝ってくれますか? ドル通貨に sを使用する最良の方法は何でしょうかBigDecimal
。たとえば、セントの場合は少なくとも小数点以下 2 桁までにするなどです。APIBigDecimal
は巨大で、どのメソッドを使用すればよいかわかりません。また、 のBigDecimal
方が精度は良いのですが、 を通過するとそれがすべて失われてしまうのではないdouble
でしょうか? newBigDecimal(24.99)
を使用すると、a を使用する場合とどう違うのdouble
でしょうか? String
または、代わりにa を使用するコンストラクターを使用する必要がありますか?
9 に答える
いくつかのヒントを次に示します。
BigDecimal
提供される精度が必要な場合は、計算に使用します (Money の値では、これが必要になることがよくあります)。NumberFormat
クラスを使用して表示します。このクラスは、異なる通貨での金額のローカリゼーションの問題を処理します。ただし、プリミティブのみを取り込みます。したがって、 への変換による精度のわずかな変化を受け入れることができる場合は、double
このクラスを使用できます。NumberFormat
クラスを使用する場合は、インスタンスのメソッドscale()
を使用しBigDecimal
て、精度と丸め方法を設定します。
PS: ご参考までに、 Java でお金の値を表現する必要がある場合BigDecimal
は、常に よりも優れdouble
ています。
PPS:
BigDecimal
インスタンスの作成
BigDecimal
プリミティブ値とString
オブジェクトを受け取るコンストラクターを提供するため、これはかなり単純です。それらを使用できますが、できればString
オブジェクトを取得するものを使用できます。例えば、
BigDecimal modelVal = new BigDecimal("24.455");
BigDecimal displayVal = modelVal.setScale(2, RoundingMode.HALF_EVEN);
BigDecimal
インスタンスの表示
setMinimumFractionDigits
およびメソッド呼び出しを使用してsetMaximumFractionDigits
、表示されるデータの量を制限できます。
NumberFormat usdCostFormat = NumberFormat.getCurrencyInstance(Locale.US);
usdCostFormat.setMinimumFractionDigits( 1 );
usdCostFormat.setMaximumFractionDigits( 2 );
System.out.println( usdCostFormat.format(displayVal.doubleValue()) );
Money Pattern について少し調べてみることをお勧めします。Martin Fowler は、彼の著書 Analysis pattern で、これについて詳しく説明しています。
public class Money {
private static final Currency USD = Currency.getInstance("USD");
private static final RoundingMode DEFAULT_ROUNDING = RoundingMode.HALF_EVEN;
private final BigDecimal amount;
private final Currency currency;
public static Money dollars(BigDecimal amount) {
return new Money(amount, USD);
}
Money(BigDecimal amount, Currency currency) {
this(amount, currency, DEFAULT_ROUNDING);
}
Money(BigDecimal amount, Currency currency, RoundingMode rounding) {
this.currency = currency;
this.amount = amount.setScale(currency.getDefaultFractionDigits(), rounding);
}
public BigDecimal getAmount() {
return amount;
}
public Currency getCurrency() {
return currency;
}
@Override
public String toString() {
return getCurrency().getSymbol() + " " + getAmount();
}
public String toString(Locale locale) {
return getCurrency().getSymbol(locale) + " " + getAmount();
}
}
使用法に来る:
Money
ではなくオブジェクトを使用してすべてのお金を表しますBigDecimal
。通貨を大きな 10 進数で表すということは、表示する場所ごとに通貨をフォーマットする必要があることを意味します。表示基準が変わると想像してみてください。あらゆる場所で編集を行う必要があります。パターンを使用する代わりにMoney
、お金のフォーマットを 1 つの場所に集中させます。
Money price = Money.dollars(38.28);
System.out.println(price);
BigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP)
セントの小数点以下2桁に切り上げたい場合に使用します。ただし、計算を行うときは、丸め誤差に注意してください。金額の丸めを行うときは、一貫性を保つ必要があります。すべての計算が完了した後、最後に1回だけ丸めを実行するか、計算を実行する前に各値に丸めを適用します。どちらを使用するかはビジネス要件によって異なりますが、一般的に、最後に丸めを行う方が理にかなっていると思います。
お金の価値のためString
に構築するときに使用します。BigDecimal
を使用するdouble
と、最後に末尾の浮動小数点値があります。これは、double
/float
値がバイナリ形式でどのように表されるかに関するコンピュータアーキテクチャによるものです。
プリミティブ数値型は、メモリに単一の値を格納するのに役立ちます。しかし、double 型と float 型を使用した計算を処理する場合、丸めの問題があります。これは、メモリ表現が値に正確にマップされないために発生します。たとえば、double 値は 64 ビットを取ると想定されていますが、Java は 64 ビットすべてを使用するわけではありません。数値の重要な部分と見なされるものだけを格納します。そのため、float 型または double 型の値を一緒に加算すると、間違った値に到達する可能性があります。
1)double
精度に制限がある場合、s を使用する 1 つの理由は、 s から作成された sBigDecimal
で操作を実現することです。BigDecimal
double
2)BigDecimal
は、スケーリングされていない任意精度の整数値と非負の 32 ビット整数スケールで構成されますが、double はプリミティブ型の値をdouble
オブジェクトにラップします。タイプのオブジェクトにはDouble
、タイプがdouble
3) 違いはないはずです
$ と精度に問題はないはずです。それを行う1つの方法は、System.out.printf