Подтвердить что ты не робот

Зачем плавать.Эпсилон, а не ноль?

В следующем коде, почему существует сравнение с float.Epsilon, а не 0?

// Coroutine to move elements
protected IEnumerator SmoothMovement (Vector3 end)
{
    // Distance computation
    float sqrRemainingDistance = (transform.position - end).sqrMagnitude;

    while(sqrRemainingDistance > float.Epsilon)
    {
        Vector3 newPostion = Vector3.MoveTowards(
            rb2D.position, end, inverseMoveTime * Time.deltaTime
        );
        rb2D.MovePosition (newPostion);
        sqrRemainingDistance = (transform.position - end).sqrMagnitude;
        yield return null;
    }
}
4b9b3361

Ответ 1

Собственно, использование float.Epsilon может не иметь здесь существенной разницы. float.Epsilon является наименьшим возможным float больше нуля (примерно 1.401298E-45), что не означает, что это наименьшая разница между любыми двумя произвольными float s. Поскольку математика с плавающей запятой неточна, разница между двумя кажущимися равными числами может быть намного больше, чем float.Epsilon. Например:

float f1 = 1.0f / 3.0f;
float f = 1.0f;

(f1 * 3).Dump();  // 1
(f1 * 3 - f).Dump();  // 2.980232E-08

При сравнении поплавков лучшей практикой является выбор разумного значения для определения того, являются ли два поплавка "близкими" равными. Это контекстное определение - например, для расстояния, 1 мм "достаточно близко"? Может быть, при строительстве собачьего дома, но не на печатной плате. Вы не собираетесь сокращать доску до тех пор, пока она не будет находиться в пределах 1.401298E-45 метров цели. Вы будете выбирать разницу, которая "достаточно близко", чтобы называть их равными.

Для движения спрайта (который я предполагаю, что то, что делается в образце) - возможно, более разумный "эпсилон" - это самое маленькое расстояние, которое может быть представлено на мониторе с высоким разрешением (или, по крайней мере, это было бы замечено человеческим глазом).

Все, что сказать, что sqrRemainingDistance > 0 может быть столь же разумным здесь, поскольку нет другого числа между 0 и float.Epsilon, что число может быть, но лучшим выбором может быть некоторое число, намного большее, чем Epsilon to определить, когда прекратить цикл. Программа может зацикливаться намного больше, чем нужно, чтобы получить "разумный" результат.

Фактически, он задокументирован на MSDN:

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

Ответ 2

Потому что математика с плавающей запятой не является точной. Связанная мной статья длинная и подробная, поэтому позвольте мне объяснить с помощью простого примера:

43,65 + 61,11 = +104,75999999999999

Причина заключается в том, как фактически сохраняются числа с плавающей точкой. Если вы не хотите погружаться в это, просто помните об общих ограничениях арифметики с плавающей запятой и не ожидайте, что они будут точно такими, какими они должны быть в соответствии с математикой, включая в этом случае 0.