web-dev-qa-db-ja.com

BigDecimalの特定の精度を設定します

[〜#〜] xsd [〜#〜] があるため、lat/lonにBigDecimalを使用する必要があります。現在、lat/lonはdoubleとしてあり、BigDecimalに変換しますが、使用する精度は約12桁のみです。私はそれを設定する方法を理解することができませんでした。誰でもこれで私を助けることができますか?

46
Jason

質問のタイトルは精度について尋ねています。 BigDecimal は、スケールと精度を区別します。スケールは小数点以下の桁数です。精度は 有効数字 の数と考えることができます。これは有効数字とも呼ばれます。

Clojureのいくつかの例。

(.scale     0.00123M) ; 5
(.precision 0.00123M) ; 3

(Clojureでは、MはBigDecimalリテラルを示します。ClojureをJavaに変換できますが、Javaよりもコンパクトであることがわかります!)

簡単にスケールを増やすことができます:

(.setScale 0.00123M 7) ; 0.0012300M

ただし、まったく同じ方法でスケールをdecreaseすることはできません。

(.setScale 0.00123M 3) ; ArithmeticException Rounding necessary

丸めモードも渡す必要があります。

(.setScale 0.00123M 3 BigDecimal/ROUND_HALF_EVEN) ;
; Note: BigDecimal would prefer that you use the MathContext rounding
; constants, but I don't have them at my fingertips right now.

そのため、スケールの変更は簡単です。しかし、精度はどうですか?これはあなたが望むほど簡単ではありません!

精度を減少するのは簡単です:

(.round 3.14159M (Java.math.MathContext. 3)) ; 3.14M

ただし、精度を上げる方法は明らかではありません。

(.round 3.14159M (Java.math.MathContext. 7)) ; 3.14159M (unexpected)

懐疑論者にとっては、これはnotであり、後続のゼロが表示されないという問題です。

(.precision (.round 3.14159M (Java.math.MathContext. 7))) ; 6 
; (same as above, still unexpected)

FWIW、Clojureは末尾のゼロに注意し、willを表示します:

4.0000M ; 4.0000M
(.precision 4.0000M) ; 5

トラックに戻ります... BigDecimal コンストラクターを使用できますが、指定した桁数よりも高い精度は設定されません。

(BigDecimal. "3" (Java.math.MathContext. 5)) ; 3M
(BigDecimal. "3.1" (Java.math.MathContext. 5)) ; 3.1M

そのため、精度をすばやく変更する方法はありません。この質問を書きながら、私が取り組んでいるプロジェクトで、これと戦うことに時間を費やしました。これは、せいぜいCRAZYTOWN APIであり、最悪の場合はバグだと考えています。人。マジ?

したがって、精度を変更する場合は、次の手順を実行する必要があります。

  1. 現在の精度を調べます。
  2. 現在のスケールを検索します。
  3. スケールの変化を計算します。
  4. 新しいスケールを設定します

Clojureコードとしてのこれらの手順:

(def x 0.000691M) ; the input number
(def p' 1) ; desired precision
(def s' (+ (.scale x) p' (- (.precision x)))) ; desired new scale
(.setScale x s' BigDecimal/ROUND_HALF_EVEN)
; 0.0007M

これは、精度を変更するための多くの手順です!

BigDecimalが既にこれを提供しないのはなぜですか?私は何かを見落としていましたか?

35
David J.

setScale() を使用できます。

double d = ...
BigDecimal db = new BigDecimal(d).setScale(12, BigDecimal.ROUND_HALF_UP);
88
Peter Lawrey
 BigDecimal decPrec = (BigDecimal)yo.get("Avg");
 decPrec = decPrec.setScale(5, RoundingMode.CEILING);
 String value= String.valueOf(decPrec);

このようにして、BigDecimalの特定の精度を設定できます。

DecPrecの値は1.5726903423607562595809913132345426でしたが、これは1.57267に丸められます。

4
E Hashmi

このコードを試してみてください...

    Integer perc = 5;
    BigDecimal spread = BigDecimal.ZERO; 
    BigDecimal perc = spread.setScale(perc,BigDecimal.ROUND_HALF_UP);
    System.out.println(perc);

結果:0.00000

0
Hakan Anlamaz