Qual é o valor da expressão algébrica? - Brainly.com.br

187

Eu tenho uma pergunta sobre junit assertEqualspara testar valores duplos. Lendo o documento da API, posso ver:

@Deprecated
public static void assertEquals(double expected, double actual)

Descontinuada. Use assertEquals (dobro esperado, dobro real, dobro epsilon)

O que o epsilonvalor significa? (Epsilon é uma letra do alfabeto grego, certo?).

Alguém pode me explicar como usá-lo?

Édipo Féderle
fonte

Respostas:

198

Epsilon é o valor pelo qual os 2 números podem ser desativados. Por isso, afirmará verdadeiro, desde queMath.abs(expected - actual) < epsilon

jberg
fonte
3
Então, qual valor devo passar como epsilon?
Emeraldhieu
15
@ Emerald214 a quantidade de precisão. Se você deseja afirmar que um valor duplo é 0D, o epsilon seria 0 (100% de precisão, sem exceções). Se você deseja uma margem de erro (digamos em graus), pode definir o epsilon como 1, o que significa, por exemplo, 64,2 ° é o mesmo que 64,8 ° (uma vez que abs (64,8-64,2) <1)
Pieter De Bie,
3
A documentação diz: "delta - o delta máximo entre o esperado e o real para o qual os dois números ainda são considerados iguais". Então eu acho que deveria ser um <=não <.
Andrew Cheong
Observando o código, vejo que ele chama o método doubleIsDifferent(para comparar valores duplos) e retorna Math.abs(d1 - d2) > delta. Portanto, se a diferença entre d1 e d2 for maior que delta, isso significa que os valores são diferentes e retornarão true. Retornará false se os valores forem considerados iguais. Esse método é chamado diretamente no assertEquals e, se retornar verdadeiro, o assertEquals chamará failNotEqualse o resultado do teste será uma falha.
Anthomaxcool #
1
@ jbert Alguém pode aconselhar qual seria o valor duplo típico do epsilon se eu estivesse trabalhando com uma média de muitos números ou fazendo desvios padrão?
simgineer 23/03/19
121

Qual versão do JUnit é essa? Eu só vi delta, não epsilon - mas isso é uma questão secundária!

No javadoc JUnit :

delta - o delta máximo entre o esperado e o real para o qual os dois números ainda são considerados iguais.

Provavelmente é um exagero, mas normalmente uso um número muito pequeno, por exemplo

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertEquals(123.456, 123.456, DELTA);
}

Se você estiver usando declarações de hamcrest , poderá usar o padrão equalTo()com duas duplas (ele não usa um delta). No entanto, se você quiser um delta, basta usar closeTo()(consulte javadoc ), por exemplo

private static final double DELTA = 1e-15;

@Test
public void testDelta(){
    assertThat(123.456, equalTo(123.456));
    assertThat(123.456, closeTo(123.456, DELTA));
}

Para sua informação, o próximo JUnit 5 também tornará o delta opcional ao pagar assertEquals()com duas duplas. A implementação (se você estiver interessado) é:

private static boolean doublesAreEqual(double value1, double value2) {
    return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2);
}
James Bassett
fonte
57

Os cálculos de ponto flutuante não são exatos - geralmente há erros de arredondamento e erros devido à representação. (Por exemplo, 0.1 não pode ser representado exatamente no ponto flutuante binário.)

Por isso, comparar diretamente dois valores de ponto flutuante para igualdade geralmente não é uma boa ideia, pois eles podem ser diferentes em uma pequena quantidade, dependendo de como foram calculados.

O "delta", como é chamado nos javadocs da JUnit , descreve a quantidade de diferença que você pode tolerar nos valores para que eles ainda sejam considerados iguais. O tamanho desse valor depende inteiramente dos valores que você está comparando. Ao comparar duplas, normalmente uso o valor esperado dividido por 10 ^ 6.

mdma
fonte
11

O fato é que dois duplos podem não ser exatamente iguais devido a problemas de precisão inerentes aos números de ponto flutuante. Com esse valor delta, você pode controlar a avaliação da igualdade com base em um fator de erro.

Além disso, alguns valores de ponto flutuante podem ter valores especiais, como NAN e -Infinity / + Infinity, que podem influenciar os resultados.

Se você realmente pretende comparar que duas duplas são exatamente iguais, é melhor compará-las como uma representação longa

Assert.assertEquals(Double.doubleToLongBits(expected), Double.doubleToLongBits(result));

Ou

Assert.assertEquals(0, Double.compareTo(expected, result));

O que pode levar essas nuances em consideração.

Não mergulhei no método Assert em questão, mas só posso supor que o anterior foi descontinuado para esse tipo de problema e o novo leva-os em consideração.

Edwin Dalorzo
fonte
2

Epsilon é uma diferença entre expectede actualvalores que você pode aceitar pensando que são iguais. Você pode definir, .1por exemplo.

Constantiner
fonte
2

Observe que, se você não estiver fazendo matemática, não há nada errado em afirmar valores exatos de ponto flutuante. Por exemplo:

public interface Foo {
    double getDefaultValue();
}

public class FooImpl implements Foo {
    public double getDefaultValue() { return Double.MIN_VALUE; }
}

Nesse caso, você quer ter certeza de que não é realmente MIN_VALUEzero -MIN_VALUEou MIN_NORMALou algum outro valor muito pequeno. Você pode dizer

double defaultValue = new FooImpl().getDefaultValue();
assertEquals(Double.MIN_VALUE, defaultValue);

mas isso receberá um aviso de descontinuação. Para evitar isso, você pode ligar assertEquals(Object, Object):

// really you just need one cast because of autoboxing, but let's be clear
assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);

E, se você realmente quer parecer inteligente:

assertEquals(
    Double.doubleToLongBits(Double.MIN_VALUE), 
    Double.doubleToLongBits(defaultValue)
);

Ou você pode simplesmente usar afirmações no estilo fluente de Hamcrest:

// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));

Se o valor que você está verificando for proveniente de algumas contas, use o epsilon.

David Moles
fonte
7
Se você deseja verificar se há exatamente iguais, defina epsilon como 0,0 - a variante Objeto não é necessária.
Mel Nicholson
-2
Assert.assertTrue(Math.abs(actual-expected) == 0)
Prakash
fonte
Ao usar números de ponto flutuante (como flutuante ou duplo), isso não funcionará de maneira confiável. Você pode revisar como os números de ponto flutuante em java são armazenados e como as operações aritméticas funcionam neles. (spoiler: espere alguns erros de arredondamento!)
Attila