72

long を使用して独自の通貨クラスを作成しようとしていましたが、BigDecimal代わりに使用する必要があるようです。誰かが私が始めるのを手伝ってくれますか? ドル通貨に sを使用する最良の方法は何でしょうかBigDecimal。たとえば、セントの場合は少なくとも小数点以下 2 桁までにするなどです。APIBigDecimalは巨大で、どのメソッドを使用すればよいかわかりません。また、 のBigDecimal方が精度は良いのですが、 を通過するとそれがすべて失われてしまうのではないdoubleでしょうか? newBigDecimal(24.99)を使用すると、a を使用する場合とどう違うのdoubleでしょうか? Stringまたは、代わりにa を使用するコンストラクターを使用する必要がありますか?

4

9 に答える 9

88

いくつかのヒントを次に示します。

  1. BigDecimal提供される精度が必要な場合は、計算に使用します (Money の値では、これが必要になることがよくあります)。
  2. NumberFormatクラスを使用して表示します。このクラスは、異なる通貨での金額のローカリゼーションの問題を処理します。ただし、プリミティブのみを取り込みます。したがって、 への変換による精度のわずかな変化を受け入れることができる場合は、doubleこのクラスを使用できます。
  3. 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()) );
于 2009-08-31T23:45:15.730 に答える
40

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);
于 2010-03-15T17:59:29.297 に答える
1

BigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP)セントの小数点以下2桁に切り上げたい場合に使用します。ただし、計算を行うときは、丸め誤差に注意してください。金額の丸めを行うときは、一貫性を保つ必要があります。すべての計算が完了した後、最後に1回だけ丸めを実行するか、計算を実行する前に各値に丸めを適用します。どちらを使用するかはビジネス要件によって異なりますが、一般的に、最後に丸めを行う方が理にかなっていると思います。

お金の価値のためStringに構築するときに使用します。BigDecimalを使用するdoubleと、最後に末尾の浮動小数点値があります。これは、double/float値がバイナリ形式でどのように表されるかに関するコンピュータアーキテクチャによるものです。

于 2009-08-31T23:45:24.280 に答える
1

プリミティブ数値型は、メモリに単一の値を格納するのに役立ちます。しかし、double 型と float 型を使用した計算を処理する場合、丸めの問題があります。これは、メモリ表現が値に正確にマップされないために発生します。たとえば、double 値は 64 ビットを取ると想定されていますが、Java は 64 ビットすべてを使用するわけではありません。数値の重要な部分と見なされるものだけを格納します。そのため、float 型または double 型の値を一緒に加算すると、間違った値に到達する可能性があります。

短いクリップをご覧ください https://youtu.be/EXxUSz9x7BM

于 2016-03-01T16:16:20.287 に答える
1

1)double精度に制限がある場合、s を使用する 1 つの理由は、 s から作成された sBigDecimalで操作を実現することです。BigDecimaldouble

2)BigDecimalは、スケーリングされていない任意精度の整数値と非負の 32 ビット整数スケールで構成されますが、double はプリミティブ型の値をdoubleオブジェクトにラップします。タイプのオブジェクトにはDouble、タイプがdouble

3) 違いはないはずです

$ と精度に問題はないはずです。それを行う1つの方法は、System.out.printf

于 2009-08-31T23:33:08.347 に答える
0

javapractices.com には、これを行う方法の広範な例があります。特にMoneyクラスを参照してください。これは、通貨の計算を直接使用するよりも簡単にすることを目的としていBigDecimalます。

このMoneyクラスの設計は、表現をより自然にすることを目的としています。例えば:

if ( amount.lt(hundred) ) {
 cost = amount.times(price); 
}

WEB4J ツールには と呼ばれる同様のクラスがありDecimal、クラスよりも少し洗練されていMoneyます。

于 2009-09-01T10:39:46.633 に答える