Estoy tratando de convertir un byte firmado en unsigned. El problema es que los datos que estoy recibiendo no están firmados y Java no admite el byte sin firmar, por lo que cuando lee los datos, los trata como firmados.
Intenté convertirlo con la siguiente solución que obtuve de Stack Overflow.
public static int unsignedToBytes(byte a)
{
int b = a & 0xFF;
return b;
}
Pero cuando nuevamente se convierte en byte, obtengo los mismos datos firmados. Estoy tratando de usar estos datos como un parámetro para una función de Java que acepta solo un byte como parámetro, por lo que no puedo usar ningún otro tipo de datos. ¿Como puedo solucionar este problema?
Respuestas:
No estoy seguro de entender tu pregunta.
Acabo de probar esto y para el byte -12 (valor con signo) devolvió el entero 244 (equivalente al valor de byte sin signo pero escrito como
int
):¿Es lo que quieres hacer?
Java no permite expresar 244 como un
byte
valor, como lo haría C. Para expresar enteros positivos arribaByte.MAX_VALUE
(127) tienes que usar otro tipo de entero, comoshort
,int
olong
.fuente
byte b = (byte)unsignedToBytes((byte) -12);
ahora intenta imprimir bEl hecho de que las primitivas estén firmadas en Java es irrelevante para la forma en que están representadas en la memoria / tránsito: un byte tiene solo 8 bits y depende de usted si lo interpreta como un rango con signo. No hay una bandera mágica que diga "esto está firmado" o "esto no está firmado".
A medida que se firman las primitivas, el compilador de Java le impedirá asignar un valor superior a +127 a un byte (o inferior a -128). Sin embargo, no hay nada que te impida rechazar un int (o short) para lograr esto:
fuente
Guía completa para trabajar con bytes sin firmar en Java:
Byte sin firmar en Java
(Fuente de esta respuesta).
El lenguaje Java no proporciona nada parecido a la
unsigned
palabra clave. A debyte
acuerdo con la especificación del lenguaje representa un valor entre −128 y 127. Por ejemplo, sibyte
se emite aint
Java interpretará el primer bit como signo y usará la extensión de signo .Dicho esto, nada le impide ver
byte
simplemente 8 bits e interpretar esos bits como un valor entre 0 y 255. Solo tenga en cuenta que no hay nada que pueda hacer para forzar su interpretación sobre el método de otra persona. Si un método acepta abyte
, entonces ese método acepta un valor entre -128 y 127 a menos que se indique explícitamente lo contrario.Aquí hay un par de conversiones / manipulaciones útiles para su conveniencia:
Conversiones a / desde int
(O, si tienes Java 8+, úsalo
Byte.toUnsignedInt
).Análisis / formateo
La mejor manera es usar las conversiones anteriores:
Aritmética
La representación de 2 complementos "simplemente funciona" para sumar, restar y multiplicar:
La división requiere la conversión manual de operandos:
fuente
No hay bytes primitivos sin signo en Java. Lo habitual es lanzarlo a un tipo más grande:
fuente
Creo que las otras respuestas han cubierto la representación de la memoria y cómo las maneja depende del contexto de cómo planea usarla. Agregaré que Java 8 agregó algo de soporte para tratar con tipos sin firmar . En este caso, podrías usar
Byte.toUnsignedInt
fuente
Una nota al margen, si desea imprimirlo, simplemente puede decir
fuente
println(b & 0xff)
es suficienteSi crees que estás buscando algo como esto.
fuente
Adamski proporcionó la mejor respuesta, pero no está del todo completa, así que lea su respuesta, ya que explica los detalles que no soy.
Si tiene una función del sistema que requiere que se le pase un byte sin signo, puede pasar un byte con signo, ya que lo tratará automáticamente como un byte sin signo.
Entonces, si una función del sistema requiere cuatro bytes, por ejemplo, 192 168 0 1 como bytes sin signo, puede pasar -64 -88 0 1, y la función seguirá funcionando, porque el acto de pasarlos a la función los anulará. .
Sin embargo, es poco probable que tenga este problema ya que las funciones del sistema están ocultas detrás de las clases para la compatibilidad multiplataforma, aunque algunos de los métodos de lectura java.io devuelven bytes no seleccionados como int.
Si desea que esto funcione, intente escribir bytes firmados en un archivo y vuelva a leerlos como bytes sin firmar.
fuente
Tú también puedes:
Explicación:
digamos
a = (byte) 133;
En la memoria se almacena como: "1000 0101" (0x85 en hexadecimal)
Por lo que su representación se traduce sin signo = 133, firmado = -123 (como complemento a 2)
Cuando el desplazamiento a la izquierda se realiza 24 bits a la izquierda, el resultado ahora es un entero de 4 bytes que se representa como:
"10000101 00000000 00000000 00000000" (o "0x85000000" en hexadecimal)
entonces nosotros tenemos
y se desplaza nuevamente a la derecha 24 bits pero se llena con ceros a la izquierda. Entonces resulta a:
"00000000 00000000 00000000 10000101" (o "0x00000085" en hexadecimal)
y esa es la representación sin signo que equivale a 133.
Si trató de emitir
a = (int) a;
, lo que sucedería es que mantiene la representación del byte del complemento de 2 y lo almacena como int también como complemento de 2:(int) "10000101" ---> "11111111 11111111 11111111 10000101"
Y eso se traduce como: -123
fuente
java.lang.Byte.toUnsignedInt(byte value)
. Y si aún no está utilizando Java 8, actualice lo antes posible. Java 7 y versiones anteriores son el final de la vida.Esto no es sustancialmente diferente de una función que acepta un número entero al que desea pasar un valor mayor que 2 ^ 32-1.
Parece que depende de cómo se defina y documente la función; Puedo ver tres posibilidades:
Puede documentar explícitamente que la función trata el byte como un valor sin signo, en cuyo caso la función probablemente debería hacer lo que espera pero parece implementarse incorrectamente. Para el caso de enteros, la función probablemente declararía el parámetro como un entero sin signo, pero eso no es posible para el caso de bytes.
Puede documentar que el valor de este argumento debe ser mayor que (o tal vez igual a) cero, en cuyo caso está haciendo un mal uso de la función (pasando un parámetro fuera de rango), esperando que haga más de lo que fue diseñado para hacer. Con cierto nivel de soporte de depuración, puede esperar que la función arroje una excepción o falle una aserción.
La documentación puede no decir nada, en cuyo caso un parámetro negativo es, bueno, un parámetro negativo y si eso tiene algún significado depende de lo que haga la función. Si esto no tiene sentido, entonces tal vez la función realmente debería definirse / documentarse como (2). Si esto es significativo de una manera no obvia (p. Ej., Los valores no negativos se usan para indexar en una matriz, y los valores negativos se usan para indexar desde el final de la matriz, entonces -1 significa el último elemento) la documentación debe decir qué significa y esperaría que no sea lo que quieres que haga de todos modos.
fuente
Si tiene una función que debe pasar un byte firmado, ¿qué espera que haga si pasa un byte sin firmar?
¿Por qué no puedes usar ningún otro tipo de datos?
Por lo general, puede usar un byte como byte sin firmar con traducciones simples o sin traducciones. Todo depende de cómo se use. Tendrás que aclarar qué tienes que hacer con él.
fuente
Aunque puede parecer molesto (proveniente de C) que Java no incluyó el byte sin signo en el lenguaje, realmente no es gran cosa ya que una simple operación "b & 0xFF" produce el valor sin signo para el byte b (firmado) en el (raro) situaciones que realmente se necesitan. Los bits en realidad no cambian, solo la interpretación (que es importante solo cuando se realizan, por ejemplo, algunas operaciones matemáticas en los valores).
fuente
x & 0xFF
todas partes donde lo necesite o repite algo como enbehaveLikeAnUnsignedByte(x)
todas partes. Esto es necesario para cada lugar donde usa un valor de byte o una matriz de bytes que no debe estar firmada, no hay una forma concebible de evitar esta repetición. No puede escribir la implementación de un protocolo que lee y escribe valores de bytes con una sola referencia a una variable de bytes. Sin embargo, su visión simplista podría explicar por qué nunca se preocuparon por solucionarlo.No hay un byte sin signo en Java, pero si desea mostrar un byte, puede hacer,
Salida:
Para obtener más información, consulte Cómo mostrar un valor hexadecimal / byte en Java .
fuente
java.lang.Byte.toUnsignedInt(byte value);
existe para esto.Según las limitaciones en Java, el byte sin signo es casi imposible en el formato de tipo de datos actual. Puede buscar otras bibliotecas de otro idioma para lo que está implementando y luego puede llamarlas utilizando JNI .
fuente
Si y no. He estado cavando con este problema. Como si entendiera esto:
El hecho es que Java ha firmado el número entero -128 a 127 .. Es posible presentar un Java no firmado con:
Si, por ejemplo, agrega -12 número firmado para que no esté firmado, obtiene 244. Pero puede usar ese número nuevamente en firmado, debe volver a firmar y volverá a ser -12.
Si intenta agregar 244 al byte de Java, saldrá de la excepción de índice de excepción.
Salud..
fuente
java.lang.Byte.toUnsignedInt(byte value);
existe para esto.Si desea bytes sin firmar en Java, simplemente reste 256 del número que le interesa. Producirá el complemento de dos con un valor negativo, que es el número deseado en bytes sin signo.
Ejemplo:
Debe usar estos trucos sucios cuando use leJOS para programar el ladrillo NXT .
fuente
speed_unsigned
está firmado. Imprímelo y mira. (Y- 256
no logra nada aquí.)