5

中心的な問題は、ログに記録する必要がある一連の double があり、それぞれ有効桁数が異なることです。数字は、有効数字の桁数が大きく異なります。0 のもの (例: 5257)、いくつかのもの (例: 1308.75)、いくつかは 7 まで (例: 124.1171875) です。基本的に、小数点以下の有効桁数が 0 から 7 桁までのすべて。

標準の Double.toString() は、有効数字が 7 桁のもの以外はすべて優れています。これは最大 6 桁であり、有効桁数はすべて無意味桁数なしで出力されます。ただし、有効数字が 7 桁の場合、toString() は最後の桁を四捨五入します。いえ

5257 -> "5257"
1308.75 -> "1308.75"
124.1171875 -> "124.117188"

もちろん、DecimalFormat("#.#######") を使用してみました。これにより、有効桁数が欠落している問題は解決されましたが、精度の低い double の多くで無効桁が出力されました。いえ

1308.75 -> "1308.7499998"

これは、1) かなりの量のスペースを浪費し (通常、1 日に 2 GB を超えるデータをログに記録する)、2) ログを使用してアプリケーションを台無しにするため、容認できません。

有効数字の識別に関しては、DecimalFormat は toString() と比較してひどいようですが、とにかくそれを修正する方法はありますか? 有効桁数の toString() スタイル処理を使用し、最大桁数を 6 から 7 に拡張したいだけです。

何か案は?ありがとう

4

3 に答える 3

7

10進値を正確に保持することに関心がある場合はBigDecimal、最初に使用する必要があります-バイナリ浮動小数点型doubleとして、基本的に不適切です。

たまたま、1308.75の動作を再現することはできません。これは、その値正確にとして表現DecimalFormatできるため、驚くことではありません。実際、1308.76でさえ1308.76として出力されるため、とにかくいくつかのヒューリスティックを適用しているように見えます。実際の値は1308.759999999999990905052982270717620849609375であるため、これは私を驚かせます。これは、コードで1308.7599999999999を使用すると、1308.76と表示されることを意味します。これは、関係する限り、まったく同じ値であるためです。これらの2つの値を区別する必要がある場合は、必ず。を使用する必要があります。doubleDecimalFormatdoubleBigDecimal

また、1308.75には有効数字6桁があり、小数点以下2桁であることに注意してください。2つの概念を区別するように注意する価値があります。

于 2011-07-29T06:00:30.410 に答える
3

私には少し奇妙に思えたので、外に出てテストしました。私はこのコードを試しました:

public class MySimpleTest
{
    public static void main(String args[])
    {
        format(5257);
        format(1308.75);
        format(124.1171875);
    }

    private static void format(double d)
    {
        DecimalFormat df = new DecimalFormat("##.#######");
        System.out.println("" + d + " -> " + df.format(d));
    }
}

そして、それは私にこの結果を与えました:

5257.0 -> 5257
1308.75 -> 1308.75
124.1171875 -> 124.1171875

おそらく「##.######」(ドットの後の # が 6 つだけ) でテストしていたか、番号の末尾に数字があった可能性があります。ポイントは、##.####### および ##.0000000 形式では、最後の小数点が丸められることです (たとえば、124.11718755 は、フォーマット前に 124.1171876 に丸められます)。切り捨てたい場合は、まず次のようにして切り捨ててみてください。

double d = 124.1171875999999;
org.apache.commons.math.util.MathUtils.round(d, 6, java.math.BigDecimal.ROUND_DOWN);
DecimalFormat df = new DecimalFormat("##.#######");
System.out.println("" + d + " -> " + df.format(d));
于 2011-07-29T06:34:17.783 に答える
-1

Jon Skeetが言及したことに加えて、それぞれが桁数のDecimalFormatの配列を保持しないのはなぜですか?

于 2011-07-29T06:11:49.410 に答える