私は倍精度数を返す Java のメソッドを持っており、メソッドを呼び出すたびに返されるすべての倍精度数を比較したい (たとえば 5 回)。
これどうやってするの?
私は倍精度数を返す Java のメソッドを持っており、メソッドを呼び出すたびに返されるすべての倍精度数を比較したい (たとえば 5 回)。
これどうやってするの?
public static boolean almostEqual(double a, double b, double eps){
return Math.abs(a-b)<eps;
}
eps は平等の尺度です。
まず、「ほぼ同じ」が何を意味するかを判断する必要があります。たとえば、ulp()java.lang.Math
というメソッドがあり、double を指定すると、その double と次の double の間の距離を返します。つまり、その数値と他の数値との最小の差です。2 つの double の差とそのメソッドを呼び出した結果を単純に比較できます。
一方、2 つの数値を互いに 1% 以内に収めたい場合もあります。その場合、同じ計算を行いますが、最大許容距離の0.01
代わりに を乗じた最初の数値を使用します。ulp()
おおよその同等性は、絶対差の観点から定義されます。絶対差が特定の、おそらく小さい数を超えない場合、比較している値は「十分に近い」と言えます。
double diff = Math.abs(actual - expected);
if (diff < 1E-7) {
// Numbers are close enough
}
「十分に近い」と「等しい」を混同しないように十分注意する必要があります。これは、この 2 つが根本的に異なるためです。等しいということは推移的です (つまり、a==b と b==c を一緒にすると、a==c となります)。十分」は他動詞ではありません。
それはあなたが似ているとはどういう意味かによって異なります。1e-6 などの絶対誤差内で 2 つの数値を比較する場合は、イプシロンを使用できます。double
スケールに関係なく2つを比較したい場合。たとえば、1.1e-20 と 1.3e-20 は似ていませんが、1.1e20 と 1.1e20+1e5 は生の値を比較できます。
public static void main(String... args) throws IOException {
test(1.1e-20, 1.3e-20);
test(1.1e20, 1.1e20 + 1e5);
}
private static void test(double a, double b) {
System.out.println(a + " and " + b + ", similar= " + similarUnscaled(a, b, 10));
}
public static boolean similarUnscaled(double a, double b, long representationDifference) {
long a2 = Double.doubleToRawLongBits(a);
long b2 = Double.doubleToRawLongBits(b);
// avoid overflow in a2 - b2
return ((a2 >= 0) == (b2 >= 0)) &&
Math.abs(a2 - b2) <= representationDifference;
}
版画
1.1E-20 and 1.3E-20, similar= false
1.1E20 and 1.100000000000001E20, similar= true
2 つの double が「ほぼ等しい」とはどういう意味ですか? これは、double が互いの許容範囲内にあることを意味します。その許容範囲のサイズ、およびその許容範囲を絶対数で表すか、2 つの double のパーセンテージで表すかは、アプリケーションによって異なります。
たとえば、フォト ビューアーに表示される 2 つの写真は、画面上で同じピクセル数を占める場合、インチ単位でほぼ同じ幅になります。したがって、許容値は、画面のピクセル サイズに基づいて計算された絶対値になります。一方、2 つの金融会社の利益は、互いの差が 0.1% 以内であれば、おそらく「ほぼ等しい」と言えます。これらは架空の例にすぎませんが、要点はアプリケーションに依存するということです。
次に、いくつかの実装について説明します。アプリケーションで絶対許容誤差が必要だとします。次に、使用できます
private static final double TOLERANCE = 0.00001;
public static boolean approxEqual(final double d1, final double d2) {
return Math.abs(d1 - d2) < TOLERANCE;
}
2 つの double を比較して使用する
approxEqual(d1, d2) && approxEqual(d1, d3) && approxEqual(d1, d4) && approxEqual(d1, d5)
5 つの double を比較します。
Apache commons-mathライブラリは、さまざまな方法で double を比較できる niceクラス( Precision
API Docsを参照) を提供します。
Precision.equals(a, b, 0.1); // Tell if |a-b| <= 0.1
Precision.equals(a, b, 10); // Tell if a and b are less than 10 Ulps apart
Precision.equalsWithRelativeTolerance(a, b, 0.05); // Tell if a and b are less than 5% apart