Ускоренная реализация Math.round? - PullRequest
7 голосов
/ 17 ноября 2009

Есть ли недостатки этого кода, который представляется более быстрой (и правильной) версией java.lang.Math.round?

public static long round(double d) {

    if (d > 0) {
        return (long) (d + 0.5d);
    } else {
        return (long) (d - 0.5d);
    }
}

Используется тот факт, что в Java усечение до длинных циклов сводится к нулю.

Ответы [ 3 ]

15 голосов
/ 17 ноября 2009

Есть некоторые особые случаи , которые обрабатывает встроенный метод, а ваш код не обрабатывает. Из документации:

  • Если аргумент NaN, результат равен 0.
  • Если аргумент имеет отрицательную бесконечность или любое значение меньше или равно значению Integer.MIN_VALUE, результат равен значению Integer.MIN_VALUE.
  • Если аргумент имеет положительную бесконечность или любое значение больше или равным значению Integer.MAX_VALUE, результат равен значению Integer.MAX_VALUE.
5 голосов
/ 17 ноября 2009

Да; Вы не учитываете переполнение или переполнение. С практической точки зрения, это может не иметь значения для вашего приложения.

3 голосов
/ 04 июля 2012

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

Math.round() реализует правило "круглая половина вверх", тогда как ваш метод round() реализует правило "круглая половина от нуля".

Например:

  • Math.round(-0.5d) => 0L
  • Your.round(-0.5d) => -1L

Это может быть или не быть проблемой для вас, но вы должны понимать, что описанный выше метод не является заменой для Math.round(), даже после того, как NaN и бесконечность уже изложены.

Другой важный вопрос: Округление отрицательных чисел в Java

Что касается производительности, то нет никаких сомнений в том, что вышеуказанный метод значительно быстрее, чем Math.round() - он работает примерно в 35% времени для случайно сгенерированных положительных и отрицательных значений. Это может быть полезной оптимизацией при вызове этого метода в узком цикле. Еще лучше (25% времени выполнения), когда даны только положительные значения, возможно из-за того, что ЦП использует прогноз ветвления .

Math.round() в конечном итоге реализуется собственным вызовом JNI, что может быть причиной разницы в производительности. Эта ошибка Sun / Oracle предполагает, что в j6u22 может быть версия на чистом Java, но я не вижу, где, и действительно, Math.round() в j6u23 работает аналогично j6u16 в моих тестах. Я не проверял на других версиях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...