2016-07-15 8 views
1

Javaの浮動小数点数を最初の0でない10進数の2桁まで切り捨てたい。例えば、0.000134から0.00013、または11.00401から11.0040です。浮動小数点数を2つの最初の0以外の10進数に切り捨てる

私が考えることができる唯一の解決策は、整数部分を取り除き、10より大きいか等しい数を得るまで10を掛けることです。次に、元の浮動小数点をnumber of multiplications小数点まで切り捨てます。

しかし、私はこの操作を頻繁に行う必要があるかもしれないので、私はより速い解決策を探しています。

私のテストコード:

public static String truncateTo2NonZero(double f) { 
    int integral = (int)f; 
    double decimal = f - integral; 
    int digits = 0; 

    while (decimal < 10) { 
     decimal *= 10; 
     digits++; 
    } 

    double ret = (int)decimal/Math.pow(10, digits); 
    ret += integral; 

    return Double.toString(ret); 
} 

public static void main(String args[]) { 
    final int TESTS = 1000000; 
    double[] floats = new double[TESTS]; 

    Random random = new Random(); 
    for (int i = 0; i < TESTS; ++i) { 
     int zeros = random.nextInt(6) + 3; // divide by 10^zeros 
     double digits = random.nextInt(100) + 100; // 3 last digits 
     floats[i] = digits/Math.pow(10,zeros) + random.nextInt(20) + 1; 
    } 

    long startTime = System.nanoTime(); 
    for (int i = 0; i < TESTS; ++i) 
     truncateTo2NonZero(floats[i]); 
    long endTime = System.nanoTime(); 

    long duration = endTime - startTime; 
    System.out.println(duration/1000000); // in milliseconds 
} 

私はWindows 7のホームプレミアム64ビットを使用しています。 java -versionの出力:

java version "1.8.0_20" 
Java(TM) SE Runtime Environment (build 1.8.0_20-b26) 
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode) 
+3

これはそのようなものではありません。ここでのOPは、動的な小数点以下の桁数、すなわち2つの最初のゼロでない10進数字を保持することを望んでいる。 – Tunaki

+0

@copeg重複しない。それはTunakiが言うようなものです。私が与えた2つの例からはかなり明らかだと思います。 – devil0150

+1

"浮動小数点" "10進数字"これらの2つのフレーズは、同じ文には表示されません。 'BigDecimal'を使うべきです。 –

答えて

1

あなたは、この表示形式のように聞こえる「切り捨て」にしたいと言うとき。それはフロートはこれのために友好的ではないと言われている。 BigDecimalsはあります。これはあなたにスタートを与えるはずですが、もちろんエラーチェックが必要です。

static String roundToLastTwoDecimalDigits(float f) { 
    // split whole number and decimals 
    String[] floatParts = new BigDecimal(f).toPlainString().split("\\."); 

    int wholeNumberPortion = Integer.parseInt(floatParts[0]); 

    // count zeroes 
    String decimalPortion = floatParts[1]; 
    int numDecimalPlaces = 0; 
    while (decimalPortion.charAt(numDecimalPlaces) == '0') 
     numDecimalPlaces++; 

    // get 3 digits to round 
    String toRound = decimalPortion.substring(numDecimalPlaces, 
      numDecimalPlaces + 3); 

    int decimalForRounding = Math.round(Float.parseFloat(toRound)/10); 

    StringBuilder sb = new StringBuilder(); 

    sb.append(wholeNumberPortion); 
    sb.append("."); 
    for (int i = 0; i < numDecimalPlaces; i++) 
     sb.append("0"); 
    sb.append(decimalForRounding); 

    return sb.toString(); 
} 
+0

ちょうどテストされ、これはより遅いです。私の方法で538と比較して3703ミリ秒、500kのランダムな浮動小数点で。 – devil0150

+1

@ devil0150 'BigDecimal'は高速であることを意図していませんが、正しいことを意図しています。 –

+0

@ devil0150あなたのコードを共有できますか?私はコンパスのようなアルゴリズムを考えていますが、計算力はあまり強くありません。しかし、リンゴとリンゴを比較していることを確認するには、コードを共有して、乱数を生成する時間とメソッドを考慮してください。また、マシン/ JVMの仕様もお知らせください。 – mohsenmadi

関連する問題