2012-02-28 9 views
32

XSDには、緯度/経度にBigDecimalを使用する必要があります。私は現在double/lonをdoubleにしてBigDecimalに変換していますが、私は約12箇所の精度しか必要としません。私はそれを設定する方法を見つけることができませんでした。誰もこれで私を助けることができますか?BigDecimalの精度を設定する

+0

あなたはコンストラクタたMathContextを与えてみましたか? – bdares

+1

正しく表示されていれば、浮動小数点精度ではなく、小数点以下の桁数について話しています。少なくとも受け入れられる答えは12桁の小数点以下12桁の精度になります。 – vbence

答えて

60

setScale()などを使用できます。

double d = ... 
BigDecimal db = new BigDecimal(d).setScale(12, BigDecimal.ROUND_HALF_UP); 
+1

Duh。私が得たエラーを振り返ってみると、丸めが必要だと言いました。私は.setScale(12)だけを行っていました。私はそれが動作することを確認した後、私はそれを答えとして行います。ありがとう。 – Jason

+0

私はなぜそれが単にキャストのようなデフォルトの丸めメソッドを使用するのではないのかわかりません、私はROUND_HALF_UPが使用されているのを見ました。それはむしろ賢明です。 ;) –

+1

+1これは今日の私のオートメーションで私を助けました:) – Brian

27

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

Clojureではいくつかの例があります。

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

(Clojureのでは、MがBigDecimalのリテラルを指定する。あなたが好きな場合は、JavaへのClojureを翻訳することができますが、私はそれは、Javaよりもコンパクトであることがわかりました!)

あなたが簡単にできます

(.setScale 0.00123M 7) ; 0.0M 

しかし、あなたは減少まったく同じように拡張性はありません:規模を増やす

012あなたも丸めモードに合格する必要があります
(.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) 

、これはないです表示されていない末尾の0の問題のみ:

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

FWIW、Clojureのはゼロと末尾に注意しているがそれらを表示します:

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. スケールの変化を計算します。 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はこれを提供していませんか?私は何か見落としましたか?

  • +0

    'BigDecimal.round(新しいMathContext(精度、RoundingModel.ROUND_HALF_EVEN))'はどうですか? –

    +1

    @PaŭloEbermannあなたは尋ねているか提案していますか?あなたはそれを試しましたか?私の答えで実行した例の詳細な結果を共有しているケア?もしそうなら、別の答えが必要だと思います。 –

    +1

    私に似ていてClojureのことを知らない人にとっては、ここに示す解決策は 'x.setScale(x.scale()+ p - x.precision()、RoundingMode.HALF_UP) x'は丸めたいBigDecimalで、 'p'はあなたが保持したい有効数字の数です。それは私のために働いているが、私が間違っている場合は私を修正! – Nateowami

    3
    BigDecimal decPrec = (BigDecimal)yo.get("Avg"); 
    decPrec = decPrec.setScale(5, RoundingMode.CEILING); 
        String value= String.valueOf(decPrec); 
    

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

    はここdecPrecの値が1.5726903423607562595809913132345426このコードを試してみてください1.57267

    0

    に四捨五入され ...だった

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

    結果:0.00000

    関連する問題