Como comparar essa seqüência de duplas são todas “aproximadamente iguais” em Java?

Eu tenho um método em java que retorna um número duplo e eu quero comparar cada número duplo que é retornado toda vez que eu chamo o método (digamos 5 vezes), para que eu possa concluir que o número retornado é quase o mesmo todas as vezes.

Como posso fazer isso?

Você deve primeiro decidir o que “quase o mesmo” significa. Por exemplo, há um método em java.lang.Math chamado ulp () que, dado um double, retorna a distância entre o double e o next; ou seja, a menor diferença possível entre esse número e qualquer outro. Você pode simplesmente comparar a diferença entre os dois duplos e o resultado de chamar esse método.

Por outro lado, talvez você queira que dois números estejam dentro de 1% um do outro. Nesse caso, faça o mesmo cálculo, mas use o primeiro número multiplicado por 0.01 vez de ulp() como a maior distância aceitável.

 public static boolean almostEqual(double a, double b, double eps){ return Math.abs(ab) 

Onde eps é a medida da igualdade.

A igualdade aproximada é definida em termos da diferença absoluta: se uma diferença absoluta não exceder um certo número, presumivelmente pequeno, então você pode dizer que os valores que você está comparando estão “próximos o suficiente”.

 double diff = Math.abs(actual - expected); if (diff < 1E-7) { // Numbers are close enough } 

Você deve ter muito cuidado para não confundir "perto o suficiente" final "igual", porque os dois são fundamentalmente diferentes: a igualdade é transitiva (ou seja, == b e b == c juntos implicam que a == c), enquanto "fechar o suficiente "não é transitivo.

Depende do que você quer dizer com similar. Se você quiser comparar dois números dentro de um erro absoluto, por exemplo, 1e-6, você pode usar o epsilon. Se você quiser comparar duas double independentemente da escala. Por exemplo, 1.1e-20 e 1.3e-20 não são semelhantes, mas 1.1e20 e 1.1e20 + 1e5 são capazes de comparar o valor bruto.

 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; } 

impressões

 1.1E-20 and 1.3E-20, similar= false 1.1E20 and 1.100000000000001E20, similar= true 

O que significa para dois duplos ser “aproximadamente igual”? Isso significa que os duplos estão dentro de alguma tolerância um do outro. O tamanho dessa tolerância, e se essa tolerância é expressa como um número absoluto ou como uma porcentagem dos dois duplos, depende da sua aplicação.

Por exemplo, duas fotos exibidas em um visualizador de fotos têm aproximadamente a mesma largura em polegadas se ocuparem o mesmo número de pixels na canvas, portanto, sua tolerância será um número absoluto calculado com base no tamanho do pixel da canvas. Por outro lado, os lucros de duas empresas financeiras são provavelmente “aproximadamente iguais” se estiverem dentro de 0,1% um do outro. Estes são apenas exemplos hipotéticos, mas o ponto é que isso depende da sua aplicação.

Agora, para alguma implementação. Vamos supor que seu aplicativo exige uma tolerância absoluta. Então você pode usar

 private static final double TOLERANCE = 0.00001; public static boolean approxEqual(final double d1, final double d2) { return Math.abs(d1 - d2) < TOLERANCE; } 

comparar duas duplas e usar

 approxEqual(d1, d2) && approxEqual(d1, d3) && approxEqual(d1, d4) && approxEqual(d1, d5) 

para comparar cinco duplos.

Você pode usar o método Guava e DoubleMath#fuzzyEquals (desde a versão 13.0):

 public static boolean fuzzyEquals(double a, double b, double tolerance) 

Retorna verdadeiro se a e b estiverem dentro da tolerância um do outro. Tecnicamente falando, isso é equivalente a Math.abs (a – b) <= tolerance || Double.valueOf (a) .equals (Double.valueOf (b)).

Casos especiais notáveis ​​incluem:

Link para documentos: https://google.github.io/guava/releases/17.0/api/docs/com/google/common/math/DoubleMath.html

    Intereting Posts