14

BigDecimal の 2 つの限られた精度の代替手段、つまり DecimalInt と DecimalLong を作成することを検討しています。これらは int と long の実際の範囲内で任意の小数点以下桁数の数値を処理でき、変更可能な形式と変更不可能な形式の両方で作成できます。私の計画は、DecimalInt を +/-999,999,999 か​​ら +/- 0.999999999 までサポートし、DecimalLong を同じように、ただし最大 18 桁までサポートすることです。

これは、スケーリングされた int または long として格納された実際の値とともに、DecimalInt の 0 ~ 9 および DecimalLong の 0 ~ 18 の 10 進数のカウント値を維持することによって行われます。通常は、通貨や株価などの少数の小数点以下の桁数 (通常は 2 ~ 4 桁) に使用されます。

必須要件は、(a) 無駄のないフットプリント (2 つのクラスと OverflowException)、および (b) すべての基本演算と意味のあるすべての Math の完全なサポートです。

結果をグーグルで検索しても、明らかなヒットは返されませんでした。それらはすべて、任意の小数に関連しているように見えました。

私の質問は次のとおりです。これはすでに行われていますか? これには、まだ実行されていない理由である隠れた微妙な点がありますか? Java が DotNet のような 10 進数型をサポートしているという噂を聞いたことがありますか。

編集:これは BigDecimal とは異なります。(a) int の配列を処理しない方がはるかに効率的であり、(b) BigInteger をラップしないため、メモリにも負担がかかりません。 (c) 変更可能なオプションがあるため、そこでも高速になります。要約すると、「BigDecimal のオーバーヘッドと double の不正確さなしに銀行残高を保存したい」などの単純なユース ケースのオーバーヘッドが少なくなります。

編集: 877.85 ではなく 1586.60-708.75=877.8499999999999 という古典的な問題を回避するために、int または long を使用してすべての計算を行うつもりです。

4

5 に答える 5

13

これが行われなかった理由は、BigDecimalとBigIntegerのオーバーヘッドが思ったほど関連性がなく、努力する価値がなく、微妙な方法で間違ってしまうリスクを回避するためだと強く思います。

あなたの例を使用すると:どんな金融アプリケーションでも、数十バイトを節約することは問題ではなく、限られた精度で取引を破ります(米国の株価は通常2〜4桁ですが、新興市場に対処したい場合、15桁の合計でパンの半分を購入する、暴走するインフレの通貨に遭遇します)。

基本的に、それは時期尚早の最適化のちょうど別のケースのように聞こえます。

于 2008-12-11T10:39:45.230 に答える
1

丸め誤差を特に心配しているほとんどの人は、ほとんどの状況で十分に機能するBigDecimalとBigIntegerを使用します。

ただし、パフォーマンスがより重要な場合は、丸めでdoubleを使用すると機能します。これは初心者には忘れられがちですが、賢明なラウンドなしで二重の結果を出すことはできず、賢明な答えを期待することはできません。

ほとんどの場合、必要なのは丸めで2倍にすることだけです。

System.out.printf("%.2f%n", 1586.60-708.75);

プリント

877.85
于 2010-11-23T23:03:13.630 に答える
0

ポータブル デバイスに焦点を当てている場合は、Realを参照してください。Real では、数値の精度を 0 ~ 16 に設定できます。これは、MIDP 携帯電話用に設計されています。

また興味深いことに、建設的実数ライブラリを見てください。軽くはないですけどね。

以下のコメントを参照すると、 Apache Commons Math Libraryを使用して分数を処理することはできませんか? うまくいかない理由はありますか?

于 2008-12-09T20:31:18.503 に答える
0

お金を処理するための固定された少数の小数点以下の桁数を見ている場合、これは通常、整数 (必要に応じて長い) セントまたは 100 分の 1 セントを保持することによって行われます。

お金を扱っている場合は、丸めの処理方法に注意する必要があります。計算が監査される場合、そのようなことをどのように行うかについての規則があります。また、いくつかの操作を正確に行うことができないことを認識していると思います(除算は明らかな例です)。

于 2008-12-10T14:38:26.763 に答える
-1

任意の精度が必要な場合は、仮数を表すために未定義のビット数が必要になるようです。つまり、仮数には何らかの配列割り当て戦略が必要になるということです。ここで独自のものを作成することもできますが、BigInteger はそれをかなり効率的に行い、機能します

表現する必要がある最小 (ゼロ以外) の値を指定する必要があります。これは 10^-(2^n) になります。n+1 は指数に割り当てるビット数です。BigDecimal では、これは 10^-(2^31) です。任意のサイズの指数を使用できますが、その範囲は誰にとっても十分なはずです。

したがって、必要なのは、表現可能な最小値をどうしたいかによって、任意の精度を与える無制限の整数仮数と固定サイズの指数です。基本的にこれは BigDecimal です。唯一の変更点は、BigDecimal で使用される int ではなく、より小さなオブジェクトを使用することです。スペースの節約に見合う価値があるかどうかは疑問です。BigDecimal は、自分で作成したソリューションよりもメモリ使用量をほとんど増やすことなく、必要なことを実行できると思います。

もちろん、必要な有効数字の最大数を選択できます。次に、仮数と指数の両方に固定サイズのストレージが必要になります。これは、ストレージが大幅に少なくなります。仮数として固定数の long を使用するだけです。

于 2008-12-09T22:43:45.287 に答える