Какой самый быстрый способ в java получить абсолютное значение double?

#java #absolute

#java #абсолютный

Вопрос:

Я использую код, подобный:

 Double getabsValue(final Object[] value){

if (value==null) return null;
if (value.lengt==0) return null;

final Double absValue=Maths.abs(value[0]);

if (absValue>0) return absValue
else return null;
  

Но в моем приложении у меня проблемы с производительностью.
Как это можно оптимизировать?

Может быть, лучше использовать?

 if (absValue>0) return absValue
else return absValue<0?-absValue:null;
  

Спасибо

Комментарии:

1. Насколько вы уверены, что Math.abs() это узкое место в производительности?

2. Компилируется ли этот код? Это не должно быть, поскольку java.math.Math#abs(...) не допускает параметра Object as.

3. это не становится быстрее, чем ваше последнее редактирование, т.е. if (absValue>0) return absValue else return -1*absValue;

4. @Shahzeb: На самом деле, это может … использование >= 0 позволит избежать Double.valueOf вызова в случае 0, а также может быть более быстрым сравнением (я подозреваю, что для этого нужно проверить только один бит). Я не знаю, есть ли кэшированное значение для Double.valueOf(0) , но если его нет, бокс может иметь существенное значение, если значение часто равно 0.

5. @JonSkeet Спасибо, что подняли этот вопрос, именно такие люди, как вы, делают ТАК, как есть сегодня.

Ответ №1:

Ну, код, который у вас есть на данный момент, даже не будет компилироваться — Math.abs(Object) насколько мне известно, вызова нет. Однако, предполагая, что у вас действительно есть приведение к Double нему, вы все время будете боксировать. Вы могли бы избежать бокса, когда значение уже больше 0, и избежать вызова, когда значение равно 0, например:

 static Double getAbsValue(Object[] values) {
    if (values == null || values.length == 0) {
        return null;
    }
    Double value = (Double) values[0];
    return value > 0 ? value
         : value == 0 ? null
         : -value;
}
  

К тому времени, когда мы переходим к последнему варианту, мы уже знаем, что значение отрицательное, поэтому нам больше не нужен вызов abs .

Не совсем понятно, в чем здесь контекст. Вы говорите, что у вас проблема с производительностью, но это определенно в этом коде?

РЕДАКТИРОВАТЬ: ваш последний код показывает:

 if (absValue>0) return absValue
else return -1*absValue;
  

Это не делает то же самое — оно не возвращает null, если массив содержит значение 0 в штучной упаковке, как это делает ваш исходный код.

Вы должны сосредоточиться на правильности перед производительностью.

Что вы хотите, чтобы ваш код делал с вводом 0? Если вы хотите, чтобы оно возвращало 0, я бы использовал:

 return value >= 0 ? value : -value;
  

Если вы хотите, чтобы он возвращал значение null, используйте код, который я предоставил изначально.

Кстати, зачем включать умножение на -1, а не просто использовать оператор унарного отрицания? Я бы ожидал, что либо компилятор, либо JIT все равно избавятся от этого, но в принципе вы не хотите выполнять умножение — вы хотите выполнить отрицание. Сделайте так, чтобы ваш код читался как можно ближе к тому, как вы описали бы свои цели.

Комментарии:

1. Извините, я забыл о приведении к (Double)

2. @user710818: Если вы выполняете кастинг to Double , то, скорее всего, автоупаковка и автоматическая распаковка, выполняемые в этом методе (и, вероятно , во всем вашем коде), оказывают гораздо большее влияние на вашу производительность, чем любые вызовы to Math.abs() . Профилируйте его и убедитесь сами.

3. @Joachim Sauer это, безусловно, верно, но есть ли способ обойти это, хотя для OP.

4. @Shahzeb: если он настаивает на изменении только опубликованного кода, то он далеко не уйдет. Ему, вероятно , потребуется внести некоторые большие изменения. Тем не менее: он должен профилировать его, прежде чем что-либо менять.

5. 1: правильность важнее производительности. Не имеет значения, как быстро вы можете сделать что-то, что неверно в 99,9% случаев. Я бы отметил, что использование double быстрее, чем использование Double или Object , но я подозреваю, что здесь это не имеет значения,

Ответ №2:

Я использую код, подобный:

 Double getabsValue(final Object[] value){
  

Почему?

Первое, что я бы сделал с этим, это переопределил подпись.

  • Бессмысленно указывать Object[] , когда оно в основном должно быть a Double[] или, по крайней мере, an Object[] , которое содержит Double , иначе оно вызовет ClassCastException .
  • Зачем указывать массив, когда вы используете только первый элемент?
  • Почему a Double , когда вам действительно нужно a double ?

Поэтому я бы переопределил его, чтобы принять один аргумент типа double . Это перемещает накладные расходы на получение данных из массива обратно вызывающему, где он может это видеть. У него может даже не быть массива, поэтому ему придется создать его для вызова этого метода. И у него уже может быть double, а не Double, и в этом случае ему или компилятору снова придется преобразовать его в Double.

Второе, что я бы сделал с этим, — это просмотреть, что осталось после этого изменения. Изменение избавляет от проверок null и length и приведения типов, поэтому все, что вам остается, — это return Math.abs(d); то, что становится ясно, что весь метод в принципе бессмыслен.

Итак, третье, что я бы сделал с ним, это удалить его.