Declarar un int sin firmar en Java
¿Hay alguna manera de declarar un int sin firmar en Java?
O la pregunta también podría plantearse de la siguiente manera: ¿Cuál es el equivalente en Java de unsigned?
Solo para decirles el contexto en el que estaba mirando la implementación de Java String.hashcode()
. Quería probar la posibilidad de colisión si el número entero fuera 32 int sin signo.
Java no tiene un tipo de datos para enteros sin signo .
Puede definir a long
en lugar de an int
si necesita almacenar valores grandes.
También puede utilizar un número entero con signo como si no tuviera signo. El beneficio de la representación en complemento a dos es que la mayoría de las operaciones (como suma, resta, multiplicación y desplazamiento a la izquierda) son idénticas a nivel binario para enteros con y sin signo. Sin embargo, algunas operaciones (división, desplazamiento a la derecha, comparación y fundición) son diferentes. A partir de Java SE 8, los nuevos métodos de la Integer
clase le permiten utilizar completamente el int
tipo de datos para realizar aritmética sin signo :
En Java SE 8 y versiones posteriores, puede utilizar el tipo de datos int para representar un entero de 32 bits sin signo, que tiene un valor mínimo de 0 y un valor máximo de 2^32-1. Utilice la clase Integer para utilizar el tipo de datos int como un entero sin signo. Se han agregado métodos estáticos como
compareUnsigned
, etc. a la clase Integer para admitir operaciones aritméticas para enteros sin signo.divideUnsigned
Tenga en cuenta que int
las variables todavía están firmadas cuando se declaran, pero ahora es posible realizar aritmética sin firmar utilizando esos métodos en la Integer
clase.
Si un valor en un int está firmado o sin firmar depende de cómo se interpretan los bits: Java interpreta los bits como un valor con signo (no tiene primitivas sin signo).
Si tiene un int que desea interpretar como un valor sin signo (por ejemplo, lee un int de un DataInputStream
que sabe que debe interpretarse como un valor sin signo), puede hacer el siguiente truco.
int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffL;
Nota: es importante que el literal hexadecimal sea un long
literal, no un int
literal, de ahí la 'L' al final.
Necesitábamos números sin signo para modelar el TINYINT
, SMALLINT
, INT
, sin signo de MySQL BIGINT
en jOOQ , razón por la cual hemos creado jOOU , una biblioteca minimalista que ofrece tipos contenedores para números enteros sin signo en Java. Ejemplo:
import static org.joou.Unsigned.*;
// and then...
UByte b = ubyte(1);
UShort s = ushort(1);
UInteger i = uint(1);
ULong l = ulong(1);
Todos estos tipos se extienden java.lang.Number
y se pueden convertir en tipos primitivos de orden superior y BigInteger
. Espero que esto ayude.
(Descargo de responsabilidad: trabajo para la empresa detrás de estas bibliotecas)
Para números sin signo, puede utilizar estas clases de la biblioteca Guava :
- Entero sin signo
- Sin firmarLargo
Soportan diversas operaciones:
- más
- menos
- veces
- modificación
- dividido por
Lo que parece faltar en este momento son los operadores de desplazamiento de bytes. Si los necesita, puede utilizar BigInteger de Java.
¿Quizás esto es lo que quisiste decir?
long getUnsigned(int signed) {
return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
getUnsigned(0)
→ 0getUnsigned(1)
→ 1getUnsigned(Integer.MAX_VALUE)
→ 2147483647getUnsigned(Integer.MIN_VALUE)
→ 2147483648getUnsigned(Integer.MIN_VALUE + 1)
→ 2147483649