20

重複の可能性:
2 つの汎用数値の値の比較

Numberの任意の 2 つのインスタンスを比較して、どちらが大きいかを調べたいと思います。ご存知のように、これらは Integer、Long、または Double の場合がありますが、BigInteger または BigDecimal の場合もあります。じゃあ何をすればいいの?

  1. Number はComparableを実装していません。
  2. doubleValue()BigDecimals または BigIntegers から精度が失われる可能性があるため、使用できません。

本当にインスタンスのテストとキャストに入る必要がありますか? これを行うライブラリが必要です。しかし、私はすでに Apache Commons と Guava をチェックしましたが、うまくいきませんでした。

編集 1:コメントはこれを指摘しました: Comparing the values of two generic Numbers。を使用してすべてを BigDecimal に変換するソリューションがありますtoString()。これを行うより良い方法は本当にありませんか?

編集 2:他の質問への回答として自分のバージョンを投稿しました。受け入れられた回答よりも効率的で堅牢でなければなりません。

4

2 に答える 2

18

type の 2 つの任意のインスタンスを比較することはできませんNumber。これは無限の操作になる可能性があるためです。2 つの無理数を想像してみてください。唯一の違いは 10 億番目の小数です。これには、数十億の小数を比較する必要があります。

Numberインスタンスをに変換しBigDecimal、必要に応じて丸めを適用してから、これらの両方を比較する必要があります。

于 2012-09-24T09:01:40.890 に答える
7

厳密に言えば、数値は比較できません。最初に比較のセマンティクスを定義する必要があります。ライブラリの使用について言及したので、おそらく Number API が提供するものだけに依存したいでしょう。

したがって、longValue() または doubleValue() のいずれかの値を比較することになります。最初に longValue() を使用して比較し、それらがequalであることが判明した場合は、 doubleValue() も比較するアプローチをお勧めします (この方法では、長いオーバーフローをキャッチしますが、値が float でない場合でも 64 ビットの長さの精度を維持します)。 :

public static int compare(Number n1, Number n2) {
    long l1 = n1.longValue();
    long l2 = n2.longValue();
    if (l1 != l2)
        return (l1 < l2 ? -1 : 1);
    return Double.compare(n1.doubleValue(), n2.doubleValue());
}

それ以外はすべて、Number API が提供するものを超える推測ゲームです。標準的な使用では、上記のコードはかなりうまく機能するはずです。はい、(たとえば) Doubles 値の範囲外にある BigIntegers または BigDecimals を渡す場合、または仮数部の精度が 53 ビットを超える差しかない場合、それらは等しいと誤って検出されますが、Number API に関する限りこの間違った結果は、「正しい」結果と見なすことができます。

于 2012-09-24T12:31:32.093 に答える