Así en el trabajo de ayer, tuve que escribir una aplicación para contar las páginas en un archivo AFP. Así que he desempolvado mi MO:DCA especificación PDF y encuentra el campo estructurado BPG (Begin Page) y sus 3 byte identificador. La aplicación necesita para funcionar en un cuadro de AIX, así que me decidí a escribir en Java.

Para una máxima eficiencia, decidí que iba a leer los 6 primeros bytes de cada campo estructurado y, a continuación, omita el resto de los bytes en el campo. Esto me llevaría:

0: Start of field byte
1-2: 2-byte length of field
3-5: 3-byte sequence identifying the type of field

Por lo que me marque el tipo de campo y el incremento de un contador de páginas, si es BPG, y yo no se si no lo es. Luego, me salto el resto de los bytes en el campo en lugar de leer a través de ellos. Y aquí, en el salto (y realmente en el campo de longitud) es donde descubrí que Java utiliza firmado bytes.

Me hizo buscar un poco en google y encontré un poco de información útil. Más útil, por supuesto, fue la instrucción de hacer un bit a bit & a 0xff para obtener el unsigned int valor. Esto era necesario para mí para conseguir una longitud que podría ser utilizado en el cálculo para el número de bytes que se debe omitir.

Ahora sé que en el 128, empezamos a contar hacia atrás desde -128. Lo que quiero saber es cómo la operación bit a bit trabaja aquí-más específicamente, ¿cómo llego a la representación binaria de un número negativo.

Si entiendo el bit a bit & correctamente, el resultado es igual a un número donde solo el común de los bits de los dos números de conjunto. Así, suponiendo byte b = -128, tendríamos:

b & 0xff //128

1000 0000-128
1111 1111 255
---------
1000 0000 128

Así que, ¿cómo iba yo a llegar a 1000 0000 para -128? ¿Cómo hago para conseguir la representación binaria de algo menos obvio como -72 o -64?

OriginalEl autor Brian Warshaw | 2010-10-02

6 Comentarios

  1. 18

    Con el fin de obtener la representación binaria de un número negativo que calcular el complemento a dos:

    • Obtener la representación binaria del número positivo
    • Invertir todos los bits
    • Agregar una

    Vamos a hacer -72 como un ejemplo:

    0100 1000    72
    1011 0111    All bits inverted
    1011 1000    Add one

    Por lo que el binario (8 bits) la representación de -72 es 10111000.

    Lo que realmente está sucediendo es la siguiente: el archivo tiene un byte con valor 10111000. Cuando se interpreta como un byte sin signo (que es probablemente lo que quieres, este es de 88.

    En Java, cuando este byte se utiliza como un int (por ejemplo, porque read() devuelve un int, o debido implícito de la promoción), se interpreta como un byte con signo, y el signo extendido a 11111111 11111111 11111111 10111000. Este es un entero con valor -72.

    Por ANDing con 0xff retener sólo el más bajo de 8 bits, por lo que su entero es ahora 00000000 00000000 00000000 10111000, que es de 88.

    +1 para la mención de que la operación se realiza en un entero con signo de extensión.
    Esto es exactamente lo que yo buscaba, muchas gracias. Esta es la razón por la que me encanta de Stackoverflow.

    OriginalEl autor Grodriguez

  2. 2

    Lo que quiero saber es cómo la operación bit a bit trabaja aquí-más específicamente, ¿cómo llego a la representación binaria de un número negativo.

    La representación binaria de un número negativo es que de la correspondiente número positivo volteado de bits con 1 agregado. Esta representación se denomina complemento a dos.

    OriginalEl autor sepp2k

  3. 1

    Supongo que la magia aquí es que el byte se almacena en un contenedor más grande, probablemente el de 32 bits int. Y si el byte se interpretó como un byte con signo se pone ampliado para representar el mismo número en la 32 bits de tipo int, que es si el bit más significativo (el primero) de los bytes 1 y, a continuación, en el de 32 bits int todos los bits a la izquierda de la 1 también se recurrió a 1 (que es debido a la forma en que los números negativos se representan, en complemento a dos).

    Ahora, si usted & 0xFF que int cortar los 1 y terminan con un «positivo» int que representa el valor del byte que usted ha leído.

    OriginalEl autor DarkDust

  4. 1

    No está seguro de lo que realmente quieres 🙂 supongo que te están preguntando cómo extraer una firma multi-byte valor? En primer lugar, veamos lo que sucede cuando usted firma para extender un solo byte:

    byte[] b = new byte[] { -128 };
    int i = b[0];
    System.out.println(i); //prints -128!

    Así, la señal está correctamente extendet a 32 bits sin hacer nada especial. El byte 1000 0000 extiende correctamente a 1111 1111 1111 1111 1111 1111 1000 0000.
    Usted ya sabe cómo suprimir el signo de extensión Y ing con 0xFF – para varios valores de byte, sólo desea que la señal de el byte más significativo para ser extendet, y el menos significativo de bytes que se desea tratar como sin signo (ejemplo se asume que el orden de byte de red de 16 bits int valor):

    byte[] b = new byte[] { -128, 1 }; //0x80, 0x01
    int i = (b[0] << 8) | (b[1] & 0xFF);
    System.out.println(i); //prints -32767!
    System.out.println(Integer.toHexString(i)); //prints ffff8001

    Usted necesita para suprimir el signo de la extensión de cada byte, excepto en el más significativo, por lo que para extraer un entero de 32 bits int a una de 64 bits de largo:

    byte[] b = new byte[] { -54, -2, -70, -66 }; //0xca, 0xfe, 0xba, 0xbe
    long l = ( b[0]         << 24) |
             ((b[1] & 0xFF) << 16) |
             ((b[2] & 0xFF) <<  8) |
             ((b[3] & 0xFF)      );
    System.out.println(l); //prints -889275714
    System.out.println(Long.toHexString(l)); //prints ffffffffcafebabe

    Nota: en sistemas basados en intel, bytes a menudo se almacenan en orden inverso (el byte menos significativo primero) porque la arquitectura x86 tiendas de entidades más grandes en este orden en la memoria. Un montón de x86 se originó el software hace uso de ella en los formatos de archivo.

    OriginalEl autor Durandal

  5. 0

    Para obtener el byte sin signo de valor puede.

    int u = b & 0xFF;

    o

    int u = b < 0 ? b + 256 : b;

    OriginalEl autor Peter Lawrey

  6. 0

    De bytes con el bit 7 establece:

    unsigned_value = signed_value + 256

    Matemáticamente cuando se compute con bytes de calcular el modulo de 256. La diferencia entre con y sin signo es que usted elija diferentes representantes de las clases de equivalencia, mientras que la representación subyacente como un patrón de bits se mantiene la misma para cada clase de equivalencia. Esto también explica por qué la suma, la resta y la multiplicación tener el mismo resultado que un patrón de bits, independientemente de si usted calcular con o sin signo enteros.

    OriginalEl autor starblue

Dejar respuesta

Please enter your comment!
Please enter your name here