減算ベースのコンパレーターを実行しない

彼らは彼らのコンパレーターを書くとき、人々は非常に頻繁に彼らの減算を好むために数を比較することを好むことに気づいた。 このアプローチは簡潔かつ簡潔ですが、残念ながら、常に正しく機能するとは限らないため、使用できません。 私自身もこれに出くわしたことがあり、頻繁に見ているのでメモを書くことにしました。



次のコードを検討してください。



import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import java.util.Collections; import java.util.List; import static java.util.Arrays.*; import static org.testng.Assert.assertEquals; public class ComparatorAlgTest { List<Integer> list1, list2; @BeforeMethod public void init(){ list1 = asList(1,2); list2 = asList(Integer.MIN_VALUE, Integer.MAX_VALUE); } void check(String name){ System.out.println(name+" list1 = " + list1); System.out.println(name+" list2 = " + list2); assertEquals(list1, asList(1,2) ); assertEquals(list2, asList(Integer.MIN_VALUE, Integer.MAX_VALUE) ); } @Test public void testWrong() { Collections.sort(list1, (Integer a, Integer b) -> ab ); Collections.sort(list2, (Integer a, Integer b) -> ab ); check("wrong"); } @Test public void testFine() { Collections.sort(list1, (Integer a, Integer b) -> a.equals(b)? 0: a>b ? 1:-1 ); Collections.sort(list2, (Integer a, Integer b) -> a.equals(b)? 0: a>b ? 1:-1 ); check("fine"); } }
      
      







これを実行すると、testWrong()が失敗し、昇順で並べ替える代わりに、降順になることがあります。



fine list1 = [1, 2]

fine list2 = [-2147483648, 2147483647]

wrong list1 = [1, 2]

wrong list2 = [2147483647, -2147483648]









実際、数値のペア(Integer.MIN_VALUE、Integer.MAX_VALUE)は、減算駆動コンパレーターが失敗する唯一の組み合わせからはほど遠いです。 結果が不正確になるためには、減算中にオーバーフローが発生することが必要かつ十分です。 たとえば、asList(-2、Integer.MAX_VALUE)に置き換えることができ、減算駆動の比較も機能しません。



All Articles