Saya perlu mengubah angka menjadi byte yang tidak ditandatangani. Angka tersebut selalu kurang dari atau sama dengan 255, sehingga akan muat dalam satu byte.
Saya juga perlu mengubah byte itu kembali menjadi angka itu. Bagaimana saya melakukannya di Jawa? Saya sudah mencoba beberapa cara dan tidak ada yang berhasil. Inilah yang saya coba lakukan sekarang:
int size = 5;
// Convert size int to binary
String sizeStr = Integer.toString(size);
byte binaryByte = Byte.valueOf(sizeStr);
dan sekarang untuk mengubah byte itu kembali menjadi angka:
Byte test = new Byte(binaryByte);
int msgSize = test.intValue();
Jelas, ini tidak berhasil. Untuk beberapa alasan, selalu mengubah angka menjadi 65
. Ada saran?
Jawaban:
Sebuah byte selalu ditandatangani di Java. Anda bisa mendapatkan nilai unsigned dengan binary-anding dengan 0xFF, meskipun:
int i = 234; byte b = (byte) i; System.out.println(b); // -22 int i2 = b & 0xFF; System.out.println(i2); // 234
sumber
0xFF
hasil berupa unsigned integer? Beberapa penjelasan akan sangat membantu.Java 8 menyediakan
Byte.toUnsignedInt
untuk dikonversibyte
keint
dengan konversi tidak bertanda tangan. Dalam JDK Oracle, ini hanya diimplementasikanreturn ((int) x) & 0xff;
karena HotSpot sudah memahami cara mengoptimalkan pola ini, tetapi pola ini dapat diintrinsifikasi pada VM lain. Lebih penting lagi, tidak diperlukan pengetahuan sebelumnya untuk memahami apa yang dilakukan oleh sebuah panggilantoUnsignedInt(foo)
.Secara total, Java 8 menyediakan metode untuk mengkonversi
byte
danshort
menjadi unsignedint
danlong
, danint
menjadi unsignedlong
. Sebuah metode untuk mengkonversibyte
ke unsignedshort
itu sengaja dihilangkan karena JVM hanya menyediakan aritmatika padaint
danlong
tetap.Untuk mengkonversi int kembali ke byte, hanya menggunakan gips:
(byte)someInt
. Konversi primitif penyempitan yang dihasilkan akan membuang semua kecuali 8 bit terakhir.sumber
Jika Anda hanya perlu mengonversi nilai 8-bit yang diharapkan dari int yang ditandatangani menjadi nilai yang tidak ditandatangani, Anda dapat menggunakan pergeseran bit sederhana:
int signed = -119; // 11111111 11111111 11111111 10001001 /** * Use unsigned right shift operator to drop unset bits in positions 8-31 */ int psuedoUnsigned = (signed << 24) >>> 24; // 00000000 00000000 00000000 10001001 -> 137 base 10 /** * Convert back to signed by using the sign-extension properties of the right shift operator */ int backToSigned = (psuedoUnsigned << 24) >> 24; // back to original bit pattern
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
Jika menggunakan sesuatu selain
int
sebagai tipe dasar, Anda jelas perlu menyesuaikan jumlah shift: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.htmlJuga, perlu diingat bahwa Anda tidak dapat menggunakan
byte
tipe, hal itu akan menghasilkan nilai yang ditandatangani seperti yang disebutkan oleh penjawab lain. Jenis primitif terkecil yang dapat Anda gunakan untuk merepresentasikan nilai 8-bit unsigned adalah ashort
.sumber
The
Integer.toString(size)
panggilan bertobat ke dalam representasi char bilangan bulat Anda, yaitu char'5'
. The ASCII representasi dari karakter yang nilai 65.Anda perlu mengurai string kembali ke nilai integer terlebih dahulu, misalnya dengan menggunakan
Integer.parseInt
, untuk mendapatkan kembali nilai int asli.Intinya, untuk konversi yang ditandatangani / tidak bertanda tangan, yang terbaik adalah meninggalkan
String
gambar dan menggunakan manipulasi bit seperti yang disarankan @JB.sumber
String sizeStr = Integer.toString(size); int sizeInt = Integer.parseInt(sizeStr); byte binaryByte = Byte.valueOf((byte) sizeInt);
String.getBytes()
menghasilkan nilai ASCII dari karakter yang terdapat dalam teks, bukan nilai numerik dari digit. Anda perlu mengurai string menjadi nilai numerik, seperti yang saya tunjukkan di atas.Solusinya bekerja dengan baik (terima kasih!), Tetapi jika Anda ingin menghindari casting dan membiarkan pekerjaan level rendah ke JDK, Anda dapat menggunakan DataOutputStream untuk menulis int dan DataInputStream untuk membacanya kembali. Mereka secara otomatis diperlakukan sebagai unsigned byte kemudian:
Untuk mengubah int menjadi byte biner;
ByteArrayOutputStream bos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(bos); int val = 250; dos.write(byteVal); ... dos.flush();
Membacanya kembali dalam:
// important to use a (non-Unicode!) encoding like US_ASCII or ISO-8859-1, // i.e., one that uses one byte per character ByteArrayInputStream bis = new ByteArrayInputStream( bos.toString("ISO-8859-1").getBytes("ISO-8859-1")); DataInputStream dis = new DataInputStream(bis); int byteVal = dis.readUnsignedByte();
Esp. berguna untuk menangani format data biner (mis. format pesan datar, dll.)
sumber
Kecuali
char
, setiap tipe data numerik lainnya di Java ditandatangani.Seperti yang dikatakan dalam jawaban sebelumnya, Anda bisa mendapatkan nilai unsigned dengan melakukan
and
operasi dengan0xFF
. Dalam jawaban ini, saya akan menjelaskan bagaimana itu terjadi.int i = 234; byte b = (byte) i; System.out.println(b); // -22 int i2 = b & 0xFF; // This is like casting b to int and perform and operation with 0xFF System.out.println(i2); // 234
Jika mesin Anda 32-bit, maka
int
tipe datanya membutuhkan 32-bit untuk menyimpan nilai.byte
hanya membutuhkan 8-bit.The
int
variabeli
direpresentasikan dalam memori sebagai berikut (sebagai integer 32-bit).0{24}11101010
Kemudian
byte
variabelb
direpresentasikan sebagai:11101010
Karena
byte
tidak bertanda tangan, nilai ini mewakili-22
. (Cari komplemen 2 untuk mempelajari lebih lanjut tentang bagaimana merepresentasikan bilangan bulat negatif dalam memori)Kemudian jika Anda mentransmisikannya ke
int
sana, itu tetap-22
karena pengecoran mempertahankan tanda sebuah angka.1{24}11101010
Nilai yang dicor
32-bit
darib
melakukanand
operasi dengan0xFF
.1{24}11101010 & 0{24}11111111 =0{24}11101010
Kemudian Anda mendapatkan
234
jawabannya.sumber
Meskipun sudah terlambat, saya ingin memberikan masukan tentang hal ini karena mungkin dapat menjelaskan mengapa solusi yang diberikan oleh JB Nizet berhasil. Saya menemukan masalah kecil ini bekerja pada pengurai byte dan konversi string sendiri. Ketika Anda menyalin dari tipe integral berukuran lebih besar ke tipe integral berukuran lebih kecil seperti yang dikatakan dokumen java ini:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3 Konversi yang dipersempit dari bilangan bulat bertanda ke tipe integral T hanya membuang semua kecuali n terendah order bits, di mana n adalah jumlah bit yang digunakan untuk merepresentasikan tipe T. Selain kemungkinan hilangnya informasi tentang besarnya nilai numerik, hal ini dapat menyebabkan tanda nilai yang dihasilkan berbeda dari tanda nilai masukan. .
Anda dapat yakin bahwa byte adalah tipe integral seperti yang dikatakan dokumen java ini https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html byte: Tipe data byte adalah 8-bit bertanda dua melengkapi integer.
Jadi dalam kasus casting integer (32 bit) menjadi byte (8 bit), Anda cukup menyalin yang terakhir (8 bit paling tidak signifikan) dari integer itu ke variabel byte yang diberikan.
int a = 128; byte b = (byte)a; // Last 8 bits gets copied System.out.println(b); // -128
Bagian kedua dari cerita ini melibatkan bagaimana Java unary dan operator biner mempromosikan operan. https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2 Konversi primitif pelebaran (§5.1.2) diterapkan untuk mengonversi salah satu atau kedua operan seperti yang ditentukan dengan aturan berikut:
Jika salah satu operan berjenis double, operan lainnya akan diubah menjadi double.
Sebaliknya, jika salah satu operand berjenis float, yang lain akan diubah menjadi float.
Sebaliknya, jika salah satu operan berjenis long, operan lainnya akan diubah menjadi long.
Jika tidak, kedua operan akan diubah menjadi tipe int.
Yakinlah, jika Anda bekerja dengan tipe integral int dan / atau lebih rendah itu akan dipromosikan menjadi int.
// byte b(0x80) gets promoted to int (0xFF80) by the & operator and then // 0xFF80 & 0xFF (0xFF translates to 0x00FF) bitwise operation yields // 0x0080 a = b & 0xFF; System.out.println(a); // 128
Saya menggaruk-garuk kepala saya di sekitar ini juga :). Ada jawaban bagus untuk ini di sini oleh rgettman. Operator bitwise di java hanya untuk integer dan long?
sumber
Jika Anda ingin menggunakan kelas pembungkus primitif, ini akan berhasil, tetapi semua jenis java ditandatangani secara default.
public static void main(String[] args) { Integer i=5; Byte b = Byte.valueOf(i+""); //converts i to String and calls Byte.valueOf() System.out.println(b); System.out.println(Integer.valueOf(b)); }
sumber
Menangani byte dan integer yang tidak ditandatangani dengan BigInteger:
byte[] b = ... // your integer in big-endian BigInteger ui = new BigInteger(b) // let BigInteger do the work int i = ui.intValue() // unsigned value assigned to i
sumber
di java 7
public class Main { public static void main(String[] args) { byte b = -2; int i = 0 ; i = ( b & 0b1111_1111 ) ; System.err.println(i); } }
hasil: 254
sumber