¿Cómo, exactamente, operadores bit a bit hacer el trabajo en Java?

john01dav:

Actualmente estoy tratando de envolver mi cabeza en torno a los operadores a nivel de bit y de desplazamiento de bits en Java. A pesar de que tienen sentido para mí en ejemplos simplificados de juguete (básicamente enteros positivos), mi entendimiento se desmorona tan pronto como negativos están involucrados, y en algunos otros casos. He intentado buscar en todo el Internet con dos motores de búsqueda e incluso he comprobado la especificación Java. No puedo encontrar ninguna fuente que describe adecuadamente cómo los operadores bit a bit y de desplazamiento de bits funcionan en Java.

Una de las funciones de la biblioteca estándar de Java que está especialmente confuso para mí es java.lang.Integer.toUnsignedLong(int). Se muestra la fuente de OpenJDK aquí (LGPLv2 con excepción ruta de clase), con un extracto en el Javadoc:

/**
 * Converts the argument to a {@code long} by an unsigned
 * conversion.  In an unsigned conversion to a {@code long}, the
 * high-order 32 bits of the {@code long} are zero and the
 * low-order 32 bits are equal to the bits of the integer
 * argument.   
 */
public static long toUnsignedLong(int x) {
    return ((long) x) & 0xffffffffL;
}

De acuerdo con la documentación oficial reproducido anteriormente, "los de orden superior 32 bits de la larga son cero y la baja de 32 bits son iguales a los bits de la argumento entero." No veo cómo esto se deduce a partir del código dentro del cuerpo del método sin embargo.

Al leer el método, la siguiente es mi línea de pensamiento positivo para x:

  1. Cuando el número entero se echó a tiempo, su signo bit / bit más significativo es cero. Como tal, muestra bit / bit más significativo del tiempo es cero y los bits de bajo orden son iguales a los del entero.
  2. A medida que el tiempo 0xfffffffftiene todas las de las de más bajo orden de 4 bytes, y porque sólo estos bytes tendrán datos en ellos, esta máscara no tiene ningún efecto y se devuelve el resultado correcto.

Al leerlo en el contexto de un negativo xsin embargo, mi entendimiento se desmorona:

  1. Cuando el número entero se cst a tiempo, su signo bit / bit más significativo es uno. Como tal, el bit de signo de la largo / más significativo es uno y los bits de orden inferior son iguales a las del número entero, excepto el bit más significativo del cuarto byte menos significativo es cero cuando es uno en el número entero.
  2. A medida que el tiempo 0xfffffffftiene todos los de los 4 bytes de orden más bajo y cero en los más altos de orden cuatro bytes, tiene el único efecto de cambiar el bit de signo en el largo, y mantiene el número entero incorrecta en los cuatro bits menos significativos intactas. Como tal, se devuelve una respuesta incorrecta de este método, cuando se cambia el bit de signo del entero a medida que avanza en el tiempo.

Cuando la prueba este método, sin embargo, consigo resultados consistentes con el Javadoc. Sospecho que estoy mal entendido uno o más puntos fundamentales sobre los operadores bit a bit en Java o su representación número entero de complemento de dos, y espero que esta pregunta puede aclarar esos puntos.

TreffnonX:

Los operadores de bits funcionan exactamente como era de esperar. Son estrictos de bits operadores y no tienen en cuenta la semántica de bits a todos.

A veces es más fácil de ejecutar a través de código usando los puntos de interrupción. Para su ejemplo específico, convertí los pasos de la operación en declaraciones atómicas e impreso con los resultados Long.toString.

int x = -57;

// step 1:
long xCast = (long) x;
System.out.println(Long.toString(xCast, 2)); // -1110011 - this is not the bitwise representation however.

long mask = 0xffffffffL;
System.out.println(Long.toString(mask, 2)); // 11111111111111111111111111111111

// step 2:
long result = ((long) x) & mask;
System.out.println(Long.toString(result, 2)); // 11111111111111111111111111000111

El paso 1 es la razón principal por la operación se ve como lo hace. En Java, se firman todos los valores numéricos (estrictamete) (caracteres están sin firmar). Esto significa que, como ha afirmado correctamente, todos los bits más altos son signo-bits. Sin embargo, la parte interesante es lo que el resto de los bits de hacer, si un número es negativo. La siguiente hilo ya cubierto los fundamentos de la 'Complemento a dos': ¿Qué es “2 de Complemento”? Lo mismo ocurre con esta wikipedia páginas: https://en.wikipedia.org/wiki/Two%27s_complement

Para ser breves, en Java, para los números enteros:

int zero = 0; // == 0b00000000_00000000_00000000_00000000

int maxPositive = Integer.MAX_VALUE; // == 0b01111111_11111111_11111111_11111111

int minus1 = -1; // == 0b11111111_11111111_11111111_11111111

int minNegative = Integer.MIN_VALUE; // == 0b10000000_00000000_00000000_00000000

Así que la razón es que todo salga bien, porque si el entero es negativo, cuando se lanza, la totalidad de los 32 bits superiores se convierten en 1s, porque de lo contrario el valor que representa el número cambiaría. efectivamente:

int x = 0b11111111_11111111_11111111_11000111;

se echa a:

long xCast = 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11000111;

Debido a que como el desarrollador espera que el método devuelva sólo los bits fijados en un principio, hay que enmascarar los bits superiores del resultado. Esto se hace en el paso 2.

Así que la respuesta a su ejemplo: La representación de los valores no flotantes en Java son el complemento a dos, y por lo tanto, cuando inteligente de fundición a un valor de int a tiempo, los bits superiores están llenos de 1s para números negativos. Por lo tanto tienen que ser eliminado.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=147075&siteId=1
Recomendado
Clasificación