Java: El poltergeist (arrays, negativos y excepciones)

Despues de varias horas volviendome loco, he descubierto que algo que en a primera vista es imposible, no lo es…

Aqui el error (aparece de modo aleatorio):

java.lang.ArrayIndexOutOfBoundsException: -2
        at RandomTextGenerator$1.run(RandomTextGenerator.java:38)
        ... cut ...

El error no me parecería extraño (no se puede usar un numero negativo como indice para un array), si no fuera porque tengo el codigo delante y ya estaba controlada esa posibilidad: si el numero es menor de cero, le cambia el signo, por tanto era aparentemente imposible esa excepcion y aún así…

private static final char[] chars = "0123456789ab...".toCharArray(); // Linea 18
// ... cut ...
final int n = rand.nextInt(); // Linea 37
os.write(chars[(n < 0 ? -n : n) % chars.length]); // Linea 38

¿Como es posible que diga -2 si nunca debería devolver un numero negativo?

Explicación:
Para un cierto valor [Integer.MIN_VALUE=(-2^31)=(-2147483648)] el resultado del cambio de signo “-N” no varía… -2147483648.
Aunque a primera vista podría parecer un bug; al parecer en una recóndita nota del API de Java [Math.abs(int n)] ya hablan del tema.
PD2: En C tambien sucede.
El origen de todo es el [complemento a 2] que se usa para la representación binaria de los numeros.

El codigo fuente completo en GitHub

Una respuesta a “Java: El poltergeist (arrays, negativos y excepciones)

  1. sergiandreplace 2012/12/06 en 17:02

    Más que un poltergesit o un bug es un “ostia, ahora que hacemos”

    El problema es que abs(MIN_VALUE) parecería lógico que fuese MAX_VALUE, pero es que precisamente si MIN_VALUE es -2^31 el de MAX_VALUE es (2^31)-1 ya que el 0 “roba” una posición de los positivos, por eso siempre los negativos llegan a uno más.

    Para mi lo lógico es que abs(MIN_VALUE) lance una excepción ya que la función no puede devolver un valor satisfactorio, pero supongo que los diseñador debieron creer que hacer que una función com abs fuese throwable la hacía muy “pesada” de usar para lo que es.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: