Точность C# при проверке float в списке с помощью метода Contains

у меня есть список floats и хотите проверить, содержит ли он уже определенное значение с List.Contains() метод. Я знаю это для float тесты равенства вы часто не можете использовать == но что-то вроде myFloat - value < 0.001.

мой вопрос в том, делает ли Contains учетная запись метода для этого или мне нужно использовать метод, который учитывает float ошибки точности для тестирования, если float находится в списке?

3 ответов


документы на List(T).Contains:

этот метод определяет равенство с помощью компаратора равенства по умолчанию, как определено реализацией объекта IEquatable<T>.Equals метод для T (тип значений в списке).

таким образом, вам нужно будет обрабатывать сравнение с порогом самостоятельно. Например, можно использовать собственный пользовательский компаратор равенства. Что-то вроде этого:--7-->

public class FloatThresholdComparer : IEqualityComparer<float>
{
    private readonly float _threshold;
    public FloatThresholdComparer(float threshold)
    {
        _threshold = threshold;
    }

    public bool Equals(float x, float y)
    {
        return Math.Abs(x-y) < _threshold;
    }

    public int GetHashCode(float f)
    {
        throw new NotImplementedException("Unable to generate a hash code for thresholds, do not use this for grouping");
    }
}

и использовать это:

var result = floatList.Contains(100f, new FloatThresholdComparer(0.01f))

Он просто использует сравнение на равенство по умолчанию для объектов, содержащихся в списке. Это будет эквивалент вызова object.Equals() при выполнении сравнений.

Если вам нужна другая реализация равенства, вы можете использовать linq Contains() перегрузка, которая принимает компаратор проверки на равенство. Тогда вам просто нужно будет реализовать это сравнение и передать его. Это должно выполняться примерно так же, но в конечном счете медленнее.


другие ответы верны, но если вы хотите альтернативное быстрое и грязное решение без написания нового компаратора равенства, вы можете использовать список.Существует Метод:

bool found = list.Exists(num => Math.Abs(num - valueToFind) < 0.001);

редактировать: Мой первоначальный ответ сказал, что выше был Linq, однако метод Exists является частью класса List. Та же концепция с использованием Linq ниже, используя IEnumerable.Любой:

bool found = list.Any(num => Math.Abs(num - valueToFind) < 0.001);