2010-07-24 114 views
16

Tôi đang cố gắng viết bộ giải mã cho một loại mã hóa rất đơn giản. Các số từ 0-255 được nhập thông qua Máy quét, các bit được đảo ngược, và sau đó được chuyển đổi thành một ký tự và được in.Làm thế nào tôi có thể đảo ngược các bit của một byte chưa ký trong Java?

Ví dụ: số 178 phải chuyển thành chữ "M".

178 là 10110010.

Đảo ngược tất cả các bit nên cung cấp cho 01.001.101, đó là 77 hay "M" như một nhân vật.

Vấn đề chính tôi có là, theo như tôi có thể nói, Java không hỗ trợ byte chưa ký. Tôi có thể đọc các giá trị dưới dạng int hoặc ngắn, nhưng sau đó các giá trị sẽ bị tắt trong quá trình chuyển đổi do các bit phụ. Lý tưởng nhất là tôi chỉ có thể sử dụng toán tử bổ sung bitwise, nhưng tôi nghĩ rằng tôi sẽ kết thúc nhận được các giá trị âm nếu tôi làm điều này với các số đã ký. Bất kỳ ý tưởng về cách tôi nên tiếp cận điều này?

+5

Bạn chọn một ví dụ thực sự xấu, vì nó cho phép hai bài đọc. – starblue

+0

Các bitmask là chính xác những gì tôi cần - Tôi không có ý tưởng bạn có thể làm điều đó. Rất hữu dụng. Cảm ơn tất cả các bạn đã trả lời. – DavidKelly999

Trả lời

0

Cách dễ nhất để làm điều này là ba giai đoạn:

  1. Đọc giá trị như một int (32 bit trong java). Nó có thể đọc như là tiêu cực nhưng chúng tôi chỉ quan tâm đến 8 bit dưới anyway. int i = scanner.nextByte();
  2. Làm đảo ngược như một int sử dụng toán tử Bitwise (như bạn nói sẽ cung cấp cho bạn 1s bit thứ tự như cao: i = ~i;
  3. Thua các bit bậc cao với một logic AND: i = i & 0xFF;

Sau đó, chỉ cần sử dụng kết quả là một nhân vật (mà thực chất là 16 bit trong java, nhưng chúng tôi sẽ chỉ sử dụng 8 trong số họ):

char c=(char)a; 
System.out.println(c); 

Tất cả với nhau:

int i = scanner.nextByte(); // change this to nextInt() depending on file format 
i = ~i; 
i = i & 0xFF; 
char c=(char)a; 
System.out.println(c); 
+0

Trong câu hỏi, nó nói "Số từ 0-255". scanner.nextByte sẽ thất bại đối với các số lớn hơn 127. –

1

Nếu Java hỗ trợ điều này, bạn có thể đọc nó thành loại lớn hơn, bitwise-compliment, sau đó bit-mask ra các bit không mong muốn.

int x = [your byte]; 
x = ~x & 0xFF; 
4

hoạt động Bitwise trong Java được định nghĩa cho int vì vậy nó làm cho tinh thần để làm việc với int hơn byte. Bạn có thể sử dụng Scanner.nextInt, thay vì Scanner.nextByte. Bạn nên xác thực đầu vào của người dùng để đảm bảo rằng tất cả các số nguyên được nhập nằm trong khoảng 0 đến 255 và hiển thị thông báo lỗi thích hợp nếu gặp phải một số ngoài phạm vi.

Khi bạn có số được lưu trữ trong một số nguyên thì hãy lật 8 bit ít quan trọng nhất bạn có thể XOR bằng 0xff.Điều này sẽ làm việc như bạn mong đợi cho tất cả nguyên liệu đầu vào từ 0 đến 255:

x ^= 0xff; 

Ví dụ:

String input = "178 0 255"; 
Scanner s = new Scanner(input); 
while (s.hasNextInt()) { 
    int x = s.nextInt(); 
    if (x < 0 || x > 255) { 
     System.err.println("Not in range 0-255: " + x); 
    } else { 
     x ^= 0xff; 
     System.out.println(x); 
    } 
} 

Kết quả:

77 
255 
0 
+0

Điều này sẽ không hoạt động nếu giá trị ban đầu được lưu trữ trong một byte, bởi vì sau đó nó sẽ được mở rộng ký hiệu thành số nguyên âm. – starblue

+0

@ starblue: Có vẻ như anh ấy đang sử dụng Máy quét. Tôi đã cập nhật câu trả lời của mình để đề cập đến điều này. –

11
~n & 0xff 

~ hiện bổ sung và mặc nhiên chuyển thành một số nguyên giống như tất cả các phép toán số, sau đó & 0xff loại bỏ mọi thứ ngoại trừ 8 bit thấp hơn để lấy giá trị chưa ký, một lần nữa làm số nguyên.

Lần đầu tiên tôi đọc câu hỏi của bạn theo cách khác, để đảo ngược thứ tự thay vì giá trị của các bit và đây là câu trả lời.

Bạn có thể sử dụng Integer.reverse() (chưa được kiểm tra):

Integer.reverse(n << 24) & 0xff 
+1

Nếu có ai đang sử dụng, phương thức 'Integer.reverse' hoạt động hoàn hảo (được thử nghiệm)! Cảm ơn btw! – Squeazer

13

tôi chỉ đơn giản sẽ sử dụng những bổ sung và thoát khỏi các bit khác bằng cách sử dụng hệ nhị phân và.

public class Conv { 
    public static void main(String[] args) { 
     int val = 178; 
     val = ~val & 0xff; 
     System.out.println((char) val); 
    } 
} 
-1

Dưới đây là byte Java, được sắp xếp theo đại diện nhị phân (00.000.000-11.111.111):

0, 1, 2, .., 126, 127, -128, -127, .., - 2, -1

00000000 là 0, 11111111 là -1

Inverted 0 là -1, ngược 1 là -2, ..., ngược 127 là -128. Vì vậy, nếu bạn muốn để đảo bit của Java byte bạn sẽ nhận được byte của bạn với dấu hiệu ngược lại và trừ một:

byte myByte = 123; 
byte myInvertedByte = -myByte-1; 
+0

Dòng mã thứ hai sẽ không biên dịch. –

0
private byte reverseBitsByte(byte x) 
{ 
    int intSize = 8; 

    byte y = 0; 
    for (int position = intSize - 1; position >= 0; position--) 
    { 
     y += ((x & 1) << position); 
     x >>= 1; 
    } 
    return y; 
} 
+0

Một số giải thích sẽ thực sự tốt đẹp. – awksp

Các vấn đề liên quan