2012-06-13 61 views
15

¿Hay alguna forma de encontrar el valor absoluto de un número sin utilizar el método Math.abs() en Java?Encontrar el valor absoluto de un número sin utilizar Math.abs()

+25

Y la razón para no querer usar ese método es ... – Thilo

+0

Es el número especificado como tipo integral, int, byte, corto, largo o es es un punto flotante (float, double) o una clase de boxeo (Integer, Double, ...) o BigDecimal, BigInteger u otra cosa? No especificado? –

+0

Necesito usarlo en un bucle. Así que estoy buscando cualquier otro mejor enfoque. – Theja

Respuesta

49

Si nos fijamos en el interior Math.abs es probable que pueda encontrar la mejor respuesta:

por ejemplo, para los flotadores:

/* 
    * 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; 
    } 
13

De esta manera:

if (number < 0) { 
    number *= -1; 
} 
+0

Conozco un caso de prueba donde esto falla. –

+0

@userunknown ¿te refieres a MIN_VALUE? – tibtof

+0

Sí, por supuesto. –

19

Sí:

abs_number = (number < 0) ? -number : number; 

Para enteros, esto funciona bien (a excepción de Integer.MIN_VALUE, cuyo valor absoluto no puede ser representado como un int).

Para números en coma flotante, las cosas son más sutiles. Por ejemplo, este método, y todos los demás métodos publicados hasta el momento, no manejarán correctamente el negative zero.

Para evitar tener que lidiar con tales sutilezas usted mismo, mi consejo sería mantener el Math.abs().

+0

Buen punto sobre los puntos flotantes. No está mal, sin embargo, aquí está la fuente de los abs dobles de java.lang.Math: 'return (a <= 0.0D)? 0.0D - a: a; 'y la versión flotante es similar. – Thilo

+0

@Thilo: El verdadero punto aquí es que las matemáticas de coma flotante están llenas de sutilezas. A menos que haya un argumento verdaderamente convincente de lo contrario, uno debería simplemente apegarse al uso de las funciones estándar. – NPE

+0

No hay concurso allí ...:-) – Thilo

0

que puede utilizar:

abs_num = (num < 0) ? -num : num; 
0

Aquí es una solución de una línea que devolverá el valor absoluto de un número:

abs_number = (num < 0) ? -num : num; 
5

Dado que Java es un lenguaje estáticamente tipado, esperaría que un método abs que toma un int devuelva un int, si espera que un float devuelva un float, para un Double, devuelva un Double. Tal vez podría devolver siempre el tipo en caja o sin caja para dobles y dobles, y así sucesivamente.

Así que necesita un método por tipo, pero ahora tiene un nuevo problema: para byte, corto, int, largo el rango para valores negativos es 1 más grande que para valores positivos.

Entonces, ¿cuál debe ser devuelto por el método

byte abs (byte in) { 
    // @todo 
} 

Si el usuario llama abs en -128? Siempre puede devolver el siguiente tipo más grande para garantizar que el rango se ajuste a todos los posibles valores de entrada. Esto ocasionará problemas por mucho tiempo, donde no existe un tipo de letra más grande y normal, y hará que el usuario siempre arroje el valor hacia abajo después de la prueba, lo que tal vez sea una molestia.

La segunda opción es lanzar una excepción aritmética. Esto evitará que se emitan y verifiquen el tipo de devolución para las situaciones donde se sabe que la entrada es limitada, de modo que X.MIN_VALUE no puede suceder. Piensa en MONTH, representado como 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; 
} 

El hábito "vamos a ignorar los raros casos de MIN_VALUE" no es una opción. Primero haz que el código funcione, luego hazlo rápido. Si el usuario necesita una solución más rápida pero con errores, debería escribirla él mismo. La solución más simple que podría funcionar significa: simple, pero no demasiado simple.

Como el código no depende del estado, el método puede y debe estar estático.Esto permite una prueba rápida:

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)); 
} 

Cojo la primera excepción y se deja correr en la segunda, sólo para demostración.

Existe una mala costumbre en la programación, que es que a los programadores les importa mucho más el código rápido que el correcto. ¡Qué pena!


Si tienes curiosidad por qué hay una más negativo que un valor positivo, tengo una diagram for you.

0

-num será igual a num para Integer.MIN_VALUE como

Integer.MIN_VALUE = Integer.MIN_VALUE * -1 
2

Utilice la clase de Matemáticas

Math.abs(num); 
+6

La pregunta dice específicamente "sin usar Math.abs()". – Kenster

2

Aunque esto no debería ser un cuello de botella como ramificación problemas en los procesadores modernos ISN' Normalmente es un problema, pero en el caso de los enteros, puede optar por una solución sin ramificaciones como se describe aquí: http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs.

(x + (x >> 31))^(x >> 31); 

Esto no fallar en el caso evidente de Integer.MIN_VALUE sin embargo, por lo que este es un uso bajo su propio riesgo solución.

+0

Sí, esto es excelente si quiere confundir a mucha gente, especialmente si nombra la función a() o algo igualmente vago – sloven

0

En el caso del valor absoluto de un entero x sin utilizar Math.abs(), condiciones o operaciones de bits, a continuación podría ser una solución posible en Java.

(int)(((long)x*x - 1)%(double)x + 1); 

Debido a que Java trata a a%b como a - a/b * b, el signo del resultado será el mismo que "un" no importa qué signo de "b" es; (x*x-1)%x será igual a abs(x)-1; tipo fundición de "largo" es para evitar el desbordamiento y double permite dividir por cero.

Una vez más, x = Integer.MIN_VALUE causará desbordamiento debido a restar 1.

Cuestiones relacionadas