Есть ли способ найти абсолютное значение числа без использования метода Math.abs() в java.
Нахождение абсолютного значения числа без использования Math.abs()
Ответы (10)
Если вы заглянете внутрь Math.abs, вы, вероятно, найдете лучший ответ:
Например, для поплавков:
/*
* Returns the absolute value of a {@code float} value.
* If the argument is not negative, the argument is returned.
* If the argument is negative, the negation of the argument is returned.
* Special cases:
* <ul><li>If the argument is positive zero or negative zero, the
* result is positive zero.
* <li>If the argument is infinite, the result is positive infinity.
* <li>If the argument is NaN, the result is NaN.</ul>
* In other words, the result is the same as the value of the expression:
* <p>{@code Float.intBitsToFloat(0x7fffffff & Float.floatToIntBits(a))}
*
* @param a the argument whose absolute value is to be determined
* @return the absolute value of the argument.
*/
public static float abs(float a) {
return (a <= 0.0F) ? 0.0F - a : a;
}
Да:
abs_number = (number < 0) ? -number : number;
Для целых чисел это работает нормально (за исключением Integer.MIN_VALUE
, абсолютное значение которого не может быть представлено как int
).
Для чисел с плавающей запятой все более тонко. Например, этот метод — и все другие опубликованные до сих пор методы — не будут правильно обрабатывать отрицательный ноль.
Чтобы не разбираться с такими тонкостями самостоятельно, я бы посоветовал придерживаться Math.abs()
.
return (a <= 0.0D) ? 0.0D - a : a;
и версия с плавающей запятой выглядит аналогично.
- person Thilo; 13.06.2012
abs()
.
- person NPE; 13.06.2012
Math.abs()
. Код в моем ответе ведет себя точно как Math.abs(int)
для Integer.MIN_VALUE
.
- person NPE; 13.06.2012
Как это:
if (number < 0) {
number *= -1;
}
Поскольку Java является статически типизированным языком, я ожидаю, что метод abs, который принимает целое число, возвращает целое число, если он ожидает, что число с плавающей запятой возвращает число с плавающей запятой, для двойного значения возвращается двойное число. Может быть, он мог бы всегда возвращать упакованный или неупакованный тип для двойных и двойных и так далее.
Таким образом, вам нужен один метод для каждого типа, но теперь у вас есть новая проблема: для byte, short, int, long диапазон для отрицательных значений на 1 больше, чем для положительных значений.
Итак, что должно быть возвращено для метода
byte abs (byte in) {
// @todo
}
Если пользователь вызывает абс на -128? Вы всегда можете вернуть следующий больший тип, чтобы диапазон гарантированно соответствовал всем возможным входным значениям. Это приведет к проблемам на долгое время, когда не существует нормального большего типа, и заставит пользователя всегда отбрасывать значение после тестирования - может быть, хлопотно.
Второй вариант — выдать арифметическое исключение. Это предотвратит приведение и проверку возвращаемого типа в ситуациях, когда известно, что ввод ограничен, например, X.MIN_VALUE не может произойти. Подумайте о MONTH, представленном как int.
byte abs (byte in) throws ArithmeticException {
if (in == Byte.MIN_VALUE) throw new ArithmeticException ("abs called on Byte.MIN_VALUE");
return (in < 0) ? (byte) -in : in;
}
Привычка "давайте игнорировать редкие случаи MIN_VALUE" не вариант. Сначала заставьте код работать, а затем сделайте его быстрым. Если пользователю нужно более быстрое, но глючное решение, он должен написать его сам. Самое простое решение, которое может сработать, означает: простое, но не слишком простое.
Поскольку код не зависит от состояния, метод можно и нужно сделать статическим. Это позволяет быстро проверить:
public static void main (String args []) {
System.out.println (abs(new Byte ( "7")));
System.out.println (abs(new Byte ("-7")));
System.out.println (abs((byte) 7));
System.out.println (abs((byte) -7));
System.out.println (abs(new Byte ( "127")));
try
{
System.out.println (abs(new Byte ("-128")));
}
catch (ArithmeticException ae)
{
System.out.println ("Integer: " + Math.abs (new Integer ("-128")));
}
System.out.println (abs((byte) 127));
System.out.println (abs((byte) -128));
}
Я перехватываю первое исключение и пропускаю его во второе просто для демонстрации.
В программировании есть плохая привычка, заключающаяся в том, что программисты гораздо больше заботятся о быстроте, чем о правильности кода. Какая жалость!
Если вам интересно, почему отрицательное значение больше, чем положительное, у меня есть для вас диаграмма.
Хотя это не должно быть узким местом, поскольку проблемы ветвления на современных процессорах обычно не являются проблемой, но в случае с целыми числами вы можете выбрать решение без ветвлений, как описано здесь: http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs.
(x + (x >> 31)) ^ (x >> 31);
Однако это не удается в очевидном случае Integer.MIN_VALUE, поэтому это решение используется на ваш страх и риск.
В случае абсолютного значения целого числа x без использования Math.abs(), условий или побитовых операций ниже может быть возможное решение в Java.
(int)(((long)x*x - 1)%(double)x + 1);
Поскольку Java обрабатывает a%b
как a - a/b * b
, знак результата будет таким же, как «a», независимо от того, какой знак у «b»; (x*x-1)%x
будет равно abs(x)-1
; приведение типа "long" предотвращает переполнение, а double
позволяет делить на ноль.
Опять же, x = Integer.MIN_VALUE
вызовет переполнение из-за вычитания 1.
Вы можете использовать :
abs_num = (num < 0) ? -num : num;
Вот однострочное решение, которое вернет абсолютное значение числа:
abs_number = (num < 0) ? -num : num;
-num будет равно num для Integer.MIN_VALUE как
Integer.MIN_VALUE = Integer.MIN_VALUE * -1
Используйте класс Математика
Math.abs(num);