Ответ 1
Epsilon - это значение, из-за которого 2 числа могут быть отключены. Таким образом, он будет отстаивать true до тех пор, пока Math.abs(expected - actual) < epsilon
У меня вопрос о junit assertEquals для проверки двойных значений. Чтение API-документа я вижу:
@Deprecated public static void assertEquals(double expected, double actual)
Устаревшие. Используйте assertEquals (double ожидаемый, двойной фактический, двойной epsilon) вместо
Что означает значение эпсилон? (Эпсилон - это буква в греческом алфавите, верно?).
Может кто-нибудь объяснить мне, как его использовать?
Epsilon - это значение, из-за которого 2 числа могут быть отключены. Таким образом, он будет отстаивать true до тех пор, пока Math.abs(expected - actual) < epsilon
Какая версия JUnit это? Я только видел дельту, а не эпсилон, но это побочный вопрос!
Из JUnit javadoc:
delta - максимальная дельта между ожидаемым и фактическим, для которой оба числа по-прежнему считаются равными.
Вероятно, это слишком сложно, но я обычно использую действительно небольшое число, например
private static final double DELTA = 1e-15;
@Test
public void testDelta(){
assertEquals(123.456, 123.456, DELTA);
}
Если вы используете hamcrest утверждения, вы можете просто использовать стандартный equalTo()
с двумя двойными (он не использует дельта). Однако, если вы хотите дельта, вы можете просто использовать closeTo()
(см. javadoc), например
private static final double DELTA = 1e-15;
@Test
public void testDelta(){
assertThat(123.456, equalTo(123.456));
assertThat(123.456, closeTo(123.456, DELTA));
}
FYI предстоящий JUnit 5 также будет сделать delta необязательным при вызове assertEquals()
с двумя удвоениями. реализация (если вам интересно):
private static boolean doublesAreEqual(double value1, double value2) {
return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2);
}
Расчеты с плавающей точкой не являются точными - часто возникают ошибки округления и ошибки из-за представления. (Например, 0,1 не может быть точно представлено в двоичной плавающей запятой.)
Из-за этого прямое сравнение двух значений с плавающей запятой для равенства обычно не является хорошей идеей, потому что они могут быть разными на небольшую сумму, в зависимости от того, как они были вычислены.
"Дельта", как она называется в JUnit javadocs, описывает величину разницы, которую вы можете терпеть в значениях для них все еще считаются равными. Размер этого значения полностью зависит от значений, которые вы сравниваете. При сравнении удвоений я обычно использую ожидаемое значение, деленное на 10 ^ 6.
Дело в том, что два двойных не могут быть точно равными из-за ошибок точности, присущих номерам с плавающей запятой. С помощью этого значения дельта вы можете контролировать оценку равенства на основе коэффициента ошибки.
Также некоторые значения с плавающей запятой могут иметь специальные значения, такие как NAN и -Infinity/+ Infinity, которые могут влиять на результаты.
Если вы действительно собираетесь сравнить, что два удвоения в точности равны, лучше сравнить их как длинное представление
Assert.assertEquals(Double.doubleToLongBits(expected), Double.doubleToLongBits(result));
или
Assert.assertEquals(0, Double.compareTo(expected, result));
Что может учитывать эти нюансы.
Я не разбираюсь в рассматриваемом методе Assert, но могу предположить, что предыдущий был устаревшим для такого рода проблем, и новый учитывает их.
Обратите внимание: если вы не выполняете математику, нет ничего плохого в утверждении точных значений с плавающей запятой. Например:
public interface Foo {
double getDefaultValue();
}
public class FooImpl implements Foo {
public double getDefaultValue() { return Double.MIN_VALUE; }
}
В этом случае вы хотите убедиться, что это действительно MIN_VALUE
, а не ноль или -MIN_VALUE
или MIN_NORMAL
или другое очень маленькое значение. Вы можете сказать
double defaultValue = new FooImpl().getDefaultValue();
assertEquals(Double.MIN_VALUE, defaultValue);
но это даст вам предупреждение об устаревании. Чтобы этого избежать, вы можете вызвать assertEquals(Object, Object)
вместо:
// really you just need one cast because of autoboxing, but let be clear
assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
И, если вы действительно хотите выглядеть умным:
assertEquals(
Double.doubleToLongBits(Double.MIN_VALUE),
Double.doubleToLongBits(defaultValue)
);
Или вы можете просто использовать утверждения Hamcrest в свободном стиле:
// equivalent to assertEquals((Object)Double.MIN_VALUE, (Object)defaultValue);
assertThat(defaultValue, is(Double.MIN_VALUE));
Если значение, которое вы проверяете, исходит от выполнения некоторой математики, однако, используйте epsilon.
Epsilon - это разница между значениями expected
и actual
, которые вы можете принять, думая, что они равны. Вы можете установить .1
, например.
Нет необходимости включать epsilon или delta.
Assert.assertTrue("Not equals", expectedDouble - actualDouble == 0);