2013-02-13 3 views
4

Как я понимаю, значения типов с плавающей запятой следует тщательно сравнивать, чтобы избежать проблем с присущими ошибками с плавающей запятой. Это можно улучшить, сравнивая значения с порогом ошибки.Сравнение значений float и double с дельта?

Например, следующее решение является более удобным для использования, чем простой тест: x == y

static float CompareRelativeError(float x, float y) { 
    return Math.Abs(x - y)/Math.Max(Math.Abs(x), Math.Abs(y)); 
} 
static bool CompareAlmostEqual(float x, float y, float delta) { 
    return x == y || CompareRelativeError(x, y) < delta; 
} 

// apologies if this is a poor example 
if (CompareAlmostEqual(1f/10f, 0.1f)) { ... } 

Полученный раствор был получен из следующего ресурса: Is it safe when compare 2 float/double directly in Java?

В то время как я не был в состоянии найти литературу, чтобы подтвердить это, мне кажется, что то же самое должно быть справедливо для сравнений, таких как x > y. Например, если x и y практически равны, как можно быть больше, чем другие ...

static bool CompareGreater(float x, float y, float delta) { 
    return x > y && !CompareAlmostEqual(x, y, delta); 
} 

И, таким образом, следующий будет действительным для x >= y:

static bool CompareGreaterOrEqual(float x, float y) { 
    return x >= y; 
} 

ли мои предположения правильные ?

+0

Возможный дубликат [Doub le.Epsilon для равенства, больше, меньше, меньше или равно, больше или равно] (http://stackoverflow.com/questions/2411392/double-epsilon-for-equality-greater-than -less -than-less-than-or-equal-to-gre) –

ответ

4

Проверка равенства - это именно то, почему метод дельта (или эпсилон) используется для значений с плавающей запятой.

например. мы хотим, чтобы 3 был равен 2.999999 ... с некоторой точностью.

Таким образом, ваш метод CompareGreaterOrEqual не является достаточным, когда определяется как:

static bool CompareGreaterOrEqual(float x, float y) { 
    return x >= y; 
} 

Оно должно быть:

static bool CompareGreaterOrEqual(float x, float y, float delta) { 
    return x >= y || CompareAlmostEqual(x, y, delta); 
} 

Примечание: x >= y в первом тесте может быть просто x > y, так как сравнение дельта заботится о равенство:

static bool CompareGreaterOrEqual(float x, float y, float delta) { 
    return x > y || CompareAlmostEqual(x, y, delta); 
} 
+0

Большое спасибо за вашу помощь! Это очень хорошо написанный ответ, и теперь я понимаю, почему «CompareAlmostEqual» также понадобится здесь. –

2

Поскольку мы уже договорились, что оператор = в этом случае делается через CompareAlmostEqual, тогда было бы также целесообразно использовать его в CompareGreaterOrEqual.

static bool CompareGreaterOrEqual(float x, float y, float delta) { 
    return x >= y || CompareAlmostEqual(x, y, delta); 
} 

Кроме того, в то время как она в значительной степени зависит от того, как вы бы использовать эти функции, я хотел бы также сделать delta постоянную переменную, которая используется во всем классе, чтобы обеспечить, используя то же значение (вместо того, чтобы передавать его в качестве аргумента).

+0

+1. Побей меня! ;) –

+1

@ MitchWheat - На самом деле, глядя на время под нашими ответами, я верю, что ты был победителем, сэр! –