2012-03-06 25 views
42

Para ciertas funciones hash en Java, sería bueno ver el valor como un entero sin signo (por ejemplo, para comparar con otras implementaciones), pero Java solo admite tipos firmados. Podemos convertir un int firmado a un "sin firmar" long como tal:¿La mejor manera de convertir un entero con signo en un largo sin firmar?

public static final int BITS_PER_BYTE = 8; 
public static long getUnsignedInt(int x) { 
    ByteBuffer buf = ByteBuffer.allocate(Long.SIZE/BITS_PER_BYTE); 
    buf.putInt(Integer.SIZE/BITS_PER_BYTE, x); 
    return buf.getLong(0); 
} 
getUnsignedInt(-1); // => 4294967295 

Sin embargo, esta solución parece un exceso de lo que realmente estamos haciendo. ¿Hay una manera más eficiente de lograr lo mismo?

Respuesta

78

¿Algo como esto?

int x = -1; 
long y = x & 0x00000000ffffffffL; 

¿O me está faltando algo?

public static long getUnsignedInt(int x) { 
    return x & 0x00000000ffffffffL; 
} 
+0

+1 derecha. No, era a mí a quien le faltaba algo; me confundí con conversiones cada vez mayores y perdí de vista el enfoque simple =) – maerics

+0

Meh, sucede. Especialmente en C++ donde hay miles de formas de hacer todo. – Mysticial

+4

¿Funcionaría 'x & 0xFFFFFFFFL' también? – Paranaix

2

otra solución.

public static long getUnsignedInt(int x) { 
    if(x > 0) return x; 
    long res = (long)(Math.pow(2, 32)) + x; 
    return res; 
} 
+4

Math.pow es muy caro y se calcula todo el tiempo. En comparación, '1l << 32' es rápido y solo lo calcula el compilador. (Y no necesita ser lanzado a largo. –

+0

Puede darme algún enlace o descripción sobre cómo funciona esta conversión, no lo puedo entender. –

+1

Porque int es de 32 bits y usa dos complementos para representarlo. puede verificar el complemento de dos en wikipedia (http://en.wikipedia.org/wiki/Two's_complement) para obtener más detalles – lmatt

7

Puede utilizar una función como

public static long getUnsignedInt(int x) { 
    return x & (-1L >>> 32); 
} 

sin embargo, en la mayoría de los casos usted no necesita hacer esto. Puede usar soluciones temporales en su lugar. p.ej.

public static boolean unsignedEquals(int a, int b) { 
    return a == b; 
} 

Para obtener más ejemplos de soluciones para el uso de valores sin firmar. Unsigned utility class

+0

Su función getUnsignedInt no funciona. Cometí un error grave en mi programa ya que no probé it.: (( – user2707175

+0

@ user2707175 cambia '>>>' a '>>' y debería funcionar –

+0

getUnsignedInt parece funcionar tal cual. '>>>' es correcto. '>>' causa la extensión del signo, y - 1L desplazado a la derecha con la extensión de signo cualquier cantidad siempre da como resultado un valor con todos. – AgentME

-3
long abs(int num){ 
    return num < 0 ? num * -1 : num; 
} 
-2

Sólo mi 2 centavos por aquí, pero yo creo que es una buena práctica utilizar:

public static long getUnsignedInt(int x) { return x & (~0L); // ~ has precedence over & so no real need for brackets }

en lugar de:

retorno x & 0xFFFFFFFFL;

En esta situación, no es su preocupación la cantidad de "F" que tiene la máscara. ¡Siempre funcionará!

+1

Esto es completamente incorrecto. El int se promueve a largo, y luego lo enmascara con una cadena de 64 bits que no hace nada. Las siguientes impresiones -1 en cambio o f 4294967295: int i = -1; long j = i & (~ 0L); System.out.println (j); – PBJ

+0

sí, es malo mío, confundí 0xFFFFFFFFL con ~ 0L, lo que es obvio que no es el caso – okoopat

Cuestiones relacionadas