1. Java / Говнокод #16711

    +79

    1. 1
    2. 2
    // Number a, Number b
    return new Double(a.doubleValue() - numericTolerance).compareTo(b.doubleValue()) < 0

    В продолжение #16698, после рефакторинга. Видимо, диагноз: ООП головного мозга.

    Запостил: Actine, 17 Сентября 2014

    Комментарии (14) RSS

    • Мож я чего не понимаю, но обычно юзают: (эпсилон<разности чисел по модулю).
      А так равные числа будут одно меньше другого при положительном numericTolerance.
      Ответить
      • ну так я шустро и переписал под a.doubleValue() - numericTolerance < b.doubleValue() (numericTolerance и есть эпсилон)
        Разность чисел по модулю это для equals, а у меня отдельные ситуации на less than / more than. Бэкграунд таков, что написал свой expression language для тестирования нашего продукта, в котором есть функциональность а-ля онлайн экселя.
        Ответить
        • a=1.0d
          b=1.0d
          eps=0.00000001d
          lessThan(a,b)=true

          Кстати подобный же хинт дал Dummy00001 в предыдущем треде.
          Ответить
          • Вообще-то так и должно быть. Всё это только для того, что значения вычитываются из таблицы, где они по дефолту округлены. Если включен эпсилон, и одно из значений 0.998 показывается в таблице округлено как 1.00, то оно не должно портить проверку на фильтр «is less than 1».
            Хотя в принципе ты прав, в таком случае вообще возникает неопределенность.
            Ответить
            • Блджад, я б наверное написал свои EpsComparator<Double>(double eps), EpsComparator<Number>(double eps) ну и ровно 1 функцию-однострочник для них.
              return (Math.abs(a-b)<eps) ? 0 : Double.compare(a,b); //checks +0.0, -0.0 and NaNs
              Ответить
              • Опять-таки, это не то, что надо по функциональности.
                Твой единый компаратор при a=0.99, b=1, eps=0.02 вернул бы 0, т.е. equals
                Мне надо, чтобы для этих чисел все три условия "a > b", "b > a" и "a == b" возвращали… true. Такая вот специфика. Поэтому отдельные функции, которые по-разному учитывают эпсилон — в сторону меньше, в сторону больше, или же абсолютно.
                Эпсилон в моей либе — не максимальная разность, при которой числа считаются равными, а максимальная разность, при которой условие должно считаться выполненным.
                Ответить
                • > Мне надо, чтобы для этих чисел все три условия "a > b", "b > a" и "a == b" возвращали… true.
                  Читается как математический ад.
                  Ответить
                  • > Читается как математический ад.
                    Да почему. Просто читай их как:
                    a ≥ b-ε
                    a ≤ b+ε
                    b-ε ≤ a ≤ b+ε
                    Ответить
                    • Между ними ещё надо несколько отступов поставить, а то всё ещё кажется, что эти условия используются в одной и той же функции.
                      Ответить
                  • А вообще, имхо, надо бы возвращать третье состояние була - unknown.

                    Крестовый boost::tribool тут пришелся бы к месту.

                    P.S. Правда тогда == будет возвращать либо false либо х.з. Ничто не истинно...
                    Ответить
                    • >Крестовый boost::tribool тут пришелся бы к месту.
                      Boolean = true, false, null
                      Или свой енум.
                      Ответить
                • > все три условия "a > b", "b > a" и "a == b" возвращали… true
                  (a > b) == true
                  (a < b) == true
                  (a == b) == true

                  // Number a, Number b
                  return true;
                  Ответить
              • Вообще говоря, "равны в эпсилон окрестности" не является отношением эквивалентности, т.к. нарушается транзитивность: из |a - b| < e и |b - c| < e не следует |a - c| < e.

                Поэтому компаратор может начать выдавать странные результаты, если, например, случайно отсортировать им список.

                Так что, кмк, правильней сделать статическую функцию с длинным говорящим названием в стиле objC, вроде equalWithinEpsilon, чтобы пореже возникало желание ей пользоваться.
                Ответить
                • Вообще говоря плавающий питух сам по себе - дерьмо.
                  Потому кмк правильней будет желание пореже им пользоваться.
                  Ответить

    Добавить комментарий