web-dev-qa-db-ja.com

ダブルを3つの有効数字に丸める

このウェブサイトの例のように、二重の値を3つの有効数字に丸める方法を誰かが知っていますか

http://www.purplemath.com/modules/rounding2.htm

24
mh377
double d = ...;
BigDecimal bd = new BigDecimal(d);
bd = bd.round(new MathContext(3));
double rounded = bd.doubleValue();
69
Sean Owen
    public String toSignificantFiguresString(BigDecimal bd, int significantFigures ){
    String test = String.format("%."+significantFigures+"G", bd);
    if (test.contains("E+")){
        test = String.format(Locale.US, "%.0f", Double.valueOf(String.format("%."+significantFigures+"G", bd)));
    }
    return test;
}
2
heights1976

手でやりたい場合:

import Java.lang.Math;

public class SigDig {

  public static void main(String[] args) {
    System.out.println("   -123.456   rounded up   to 2 sig figures is " + sigDigRounder(-123.456, 2,  1));
    System.out.println("     -0.03394 rounded down to 3 sig figures is " + sigDigRounder(-0.03394, 3, -1));
    System.out.println("    474       rounded up   to 2 sig figures is " + sigDigRounder(474, 2,  1));
    System.out.println("3004001       rounded down to 4 sig figures is " + sigDigRounder(3004001, 4, -1));
  }

  public static double sigDigRounder(double value, int nSigDig, int dir) {

    double intermediate = value/Math.pow(10,Math.floor(Math.log10(Math.abs(value)))-(nSigDig-1));

    if(dir > 0)      intermediate = Math.ceil(intermediate);
    else if (dir< 0) intermediate = Math.floor(intermediate);
    else             intermediate = Math.round(intermediate);

    double result = intermediate * Math.pow(10,Math.floor(Math.log10(Math.abs(value)))-(nSigDig-1));

    return(result);

  }
}

上記のメソッドは、doubleを有効数字の望ましい数に丸め、負の数を処理し、切り上げまたは切り捨てを明示的に指示できます

2
awwsmm

Sean Owen( https://stackoverflow.com/a/7548871/274677 )の答えには何も問題はありません。ただし、ユースケースによっては、文字列表現に到達したい場合があります。その場合、IMOはBigDecimalスペースにいる間に変換するのが最善です。

_bd.toPlainString();
_

...それがあなたのユースケースである場合、オーエンの答えから改変されたコードが以下を生成することにイライラするかもしれません:

_d = 0.99, significantDigits = 3 ==> 0.99
_

...より正確な_0.990_の代わりに。

ユースケースでそのようなことが重要な場合は、オーエンの回答に次のように適応することをお勧めします。 toPlainString()を呼び出す代わりに、BigDecimal自体を返すこともできます—完全を期すために、この方法で提供しています。

_public static String setSignificanDigits(double value, int significantDigits) {
    if (significantDigits < 0) throw new IllegalArgumentException();

    // this is more precise than simply doing "new BigDecimal(value);"
    BigDecimal bd = new BigDecimal(value, MathContext.DECIMAL64);
    bd = bd.round(new MathContext(significantDigits, RoundingMode.HALF_UP));
    final int precision = bd.precision();
    if (precision < significantDigits)
    bd = bd.setScale(bd.scale() + (significantDigits-precision));
    return bd.toPlainString();
}    
_