13

与えられた精度でdoubleをstringに変換する必要があります。String.format("%.3f", value)(またはDecimalFormat)は機能しますが、ベンチマークでは、それほど高速ではないDouble.toString変換(私のマシンで100万の数値を変換するのに約1〜3秒)と比較しても遅いことが示されています。

それを行うためのより良い方法はありますか?

更新:ベンチマーク結果

0から1000000までの乱数、結果はミリ秒あたりの操作数(Java 1.7.0_45)

Benchmark                                    Mean   Mean error    Units

String_format                             747.394       13.197   ops/ms
BigDecimal_toPlainString                 1349.552       31.144   ops/ms
DecimalFormat_format                     1890.917       28.886   ops/ms
Double_toString                          3341.941       85.453   ops/ms
DoubleFormatUtil_formatDouble            7760.968       87.630   ops/ms
SO_User_format                          14269.388      168.206   ops/ms

アップデート:

Java 10、+リュウ

                                Mode  Cnt      Score      Error   Units
String_format                  thrpt   20    998.741 ±   52.704  ops/ms
BigDecimal_toPlainString       thrpt   20   2079.965 ±  101.398  ops/ms
DecimalFormat_format           thrpt   20   2040.792 ±   48.378  ops/ms
Double_toString                thrpt   20   3575.301 ±  112.548  ops/ms
DoubleFormatUtil_formatDouble  thrpt   20   7206.281 ±  307.348  ops/ms
ruy_doubleToString             thrpt   20   9626.312 ±  285.778  ops/ms
SO_User_format                 thrpt   20  17143.901 ± 1307.685  ops/ms
4

4 に答える 4

19

免責事項:速度が絶対的な要件である場合にのみ、これを使用することをお勧めします。

私のマシンでは、以下は約 130 ミリ秒で 100 万回の変換を行うことができます。

 private static final int POW10[] = {1, 10, 100, 1000, 10000, 100000, 1000000};

 public static String format(double val, int precision) {
     StringBuilder sb = new StringBuilder();
     if (val < 0) {
         sb.append('-');
         val = -val;
     }
     int exp = POW10[precision];
     long lval = (long)(val * exp + 0.5);
     sb.append(lval / exp).append('.');
     long fval = lval % exp;
     for (int p = precision - 1; p > 0 && fval < POW10[p]; p--) {
         sb.append('0');
     }
     sb.append(fval);
     return sb.toString();
 }

提示されたコードにはいくつかの欠点があります: の限られた範囲しか処理できず、doublesNaN を処理しません。POW10前者は、配列を拡張することで (部分的にしか) 対処できません。後者は、コードで明示的に処理できます。

于 2012-05-11T15:15:06.673 に答える
8

速度と精度の両方が必要な場合は、xmlgraphics-commons で高速な DoubleFormatUtil クラスを開発しました: http://xmlgraphics.apache.org/commons/changes.html#version_1.5rc1

そこにコードが表示されます: http://svn.apache.org/viewvc/xmlgraphics/commons/trunk/src/java/org/apache/xmlgraphics/util/DoubleFormatUtil.java?view=markup

DecimalFormat/BigDecimal の両方よりも高速で、Double.toString と同じくらい高速で、正確で、十分にテストされています。Apache License 2.0 の下でライセンスされているため、必要に応じて使用できます。

于 2012-10-02T09:42:52.967 に答える
-2

これはベンチマークしていませんが、BigDecimalを使用するのはどうですか?

BigDecimal bd = new BigDecimal(value).setScale(3, RoundingMode.HALF_UP);
return bd.toString();
于 2012-05-11T14:57:43.520 に答える