Более быстрая реализация математики.круглый?
Есть ли какие-либо недостатки в этом коде, который, по-видимому, является более быстрой (и правильной) версией 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 ответа:
Есть некоторые особые случаи, которые обрабатываются встроенным методом, но не обрабатываются вашим кодом. Из документации:
- если аргумент равен
Если аргумент равен отрицательной бесконечности или любому значению, меньшему или равному значениюNaN
, то результат равен 0.Integer.MIN_VALUE
, то результат равен значениюInteger.MIN_VALUE
.- если аргументом является положительная бесконечность или любое значение больше или равный значению
Integer.MAX_VALUE
, результат равен значениюInteger.MAX_VALUE
.
Да; вы не учитываете недостаточный поток или переполнение. Прагматически говоря, это может не иметь значения для вашего приложения.
Я проверял это, и есть один ключевой потенциальный недостаток, который еще не был описан здесь: вы меняете метод округления tie-breaking.
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 может быть версия pure-Java, но я не вижу, где, и действительноMath.round()
в j6u23 выполняет аналогично j6u16 в моих тестах. Я не тестировал на других версиях.