2010-11-16 16 views
5

Tôi đã đặt câu hỏi về thao tác hex và bitwise (ở đây và ở nơi khác) trong tuần qua đang cố gắng quấn đầu quanh đại diện của chúng trong Java. Sau nhiều Googling và chagrin tôi phải hỏi một thời gian cuối cùng làm thế nào để thực hiện số học logic trên bit mà nên được unsigned, nhưng được đại diện như đã ký trong Java.Thực hiện các thay đổi trái ngược bit trên dữ liệu "đã ký" trong Java - tốt hơn để chuyển sang JNI?

OK: Tôi đang chuyển một chương trình C# sang Java. Chương trình xử lý thao tác bitmap và phần lớn dữ liệu trong ứng dụng được thể hiện là byte, một số nguyên 8 bit không dấu. Có nhiều đề xuất thay vì sử dụng kiểu dữ liệu short trong Java để "bắt chước" càng gần số nguyên 8 byte không dấu.

Tôi không tin điều đó có thể xảy ra với tôi vì mã C# đang thực hiện nhiều thao tác chuyển và AND khác nhau với dữ liệu byte của tôi. Ví dụ, nếu data là một mảng byte, và khối mã này tồn tại trong C#:

int cmdtype = data[pos] >> 5; 
int len = (data[pos] & 0x1F) + 1; 

if (cmdtype == 7) 
{ 
    cmdtype = (data[pos] & 0x1C) >> 2; 
    len = ((data[pos] & 3) << 8) + data[pos + 1] + 1; 
    pos++; 
} 

Nó không phải là một vấn đề đơn giản chỉ đúc data như một short và đang được thực hiện với nó để làm cho nó làm việc trong Java . Theo như logic là có liên quan các yêu cầu dữ liệu của tôi ở trong 8-bit unsigned là đáng kể; 16-bit unsigned sẽ vít toán học như trên lên. Tôi có ở đây không? Thật vậy, sau khi đã "đúc giả" trước đây byte với 0XFFchar bằng Java và không nhận được kết quả phù hợp, tôi sợ rằng tôi đã đạt đến kết thúc chết.

Bây giờ, trong một phần khác của mã, tôi đang thực hiện một số thao tác bitmap pixel. Vì đó là một quá trình chạy dài, tôi quyết định thực hiện cuộc gọi đến mã nguồn gốc thông qua JNI. Gần đây tôi nhận ra rằng trong đó tôi có thể sử dụng loại dữ liệu uint8_t và có được đại diện gần nhất với loại dữ liệu C# byte.

Giải pháp để làm cho tất cả chức năng phụ thuộc dữ liệu của tôi có hoạt động trong JNI không? Điều đó có vẻ rất không hiệu quả, cả để viết lại và thực hiện. Là giải pháp để làm lại toán học trong Java để logic vẫn giữ nguyên? Điều đó có vẻ như đúng, nhưng có khả năng gây ra chứng phình động mạch, chưa kể đến toán học bị lỗi.

Tôi đánh giá cao mọi đề xuất.

+0

Bạn có thể thêm nhận xét cho biết C# có so với Java ở mỗi bước trong đoạn mã không? Tôi không nghĩ rằng tôi có thể giải đố tất cả các điểm trong đoạn mã đó, nơi bạn có thể tự mình gặp vấn đề. –

+0

Tôi không có bất cứ điều gì tôi sẽ phân loại như là một câu trả lời, nhưng nếu bạn đang làm rất nhiều twiddling bit, tôi đề nghị viết một lớp đơn giản bằng cách sử dụng JNI thực hiện điều này hơn là làm rất nhiều đúc. Điều đó sẽ làm tổn thương hiệu suất, khả năng gỡ lỗi và khả năng đọc. Bất kể, tôi vẫn sẽ cấu hình mã trước khi chuyển đổi mọi thứ thành JNI. Tập trung vào các lĩnh vực cần nhất. –

+0

@ John Tôi không đề xuất làm lại tất cả trong JNI - Tôi chỉ tự hỏi nếu đó là một giải pháp khả thi. – GJTorikian

Trả lời

3

Chỉ cần một lưu ý: Bạn không thể cast trực tiếp đến short, bởi vì số âm sẽ được mở rộng một cách logic.

Tức là, byte 1111 1101 (-5) khi trực tiếp truyền tới short sẽ dẫn đến 1111 1111 1111 1101 (-5), không phải 0000 0000 1111 1101 (253).Bạn phải loại bỏ những hàng đầu với AND hoạt động khi bạn cast:

short shortValue = ((short)(byteValue)) & 0xFF; 

Tôi biết thao tác bit phức tạp như thế này là có thể, bởi vì tôi đã làm điều này chính xác trong việc xử lý một giao thức thông điệp nhị phân di sản với một ứng dụng Swing Java . Tôi sẽ đánh giá cao đề nghị bằng cách nào đó trừu tượng này đi để bạn chỉ phải đối phó với nó một lần. Cho dù đó có nghĩa là gói "byte" của bạn trong một lớp để lưu trữ chúng dưới dạng quần short và xử lý các hoạt động chuyển đổi hay xác định một tiện ích tĩnh thực hiện phép chuyển đổi và bit trong một lần truyền, để bạn luôn lưu trữ các byte.

+0

Tôi nghĩ rằng bộ não của tôi chỉ là chiên. nếu tôi thực hiện thao tác lật và phép diễn thì phép toán bitwise của tôi vẫn giữ nguyên? Như tôi đã nói trước đây, tôi đã "đúc giả" với kỹ thuật chính xác mà bạn mô tả, chỉ sử dụng một char thay thế. – GJTorikian

2

Java có >>> (lưu ý ba ký tự ">", không chỉ hai) toán tử thay đổi bên phải chưa ký. Điều này nên giữ cho C# phong cách phải dịch chuyển ít nhất (các bit trên được xóa thành 0, không được ký).

Theo như đúc thành 'ngắn', C# gộp tất cả các byte đó thành số nguyên 32 bit trước khi chuyển. Bí quyết duy nhất là, C# thực hiện một phép đúc không dấu (chỉ điền 24 bit trên với 0, bất kể giá trị của bit 7). Nếu bạn đã đúc để ngắn trong Java, bạn nên chỉ có thể nói điều gì đó như:

short shortCast = ((short)byteVal) & 0xff; 
short shiftedShortCast = shortCast << whatever; 
+0

Đúng là C# chuyển thành một 'int', nhưng nó cũng có khái niệm về các kiểu unsigned, giữ cho những cái dẫn đầu từ mở rộng trong những gì sẽ là số âm. – jdmichal

+0

Điểm tốt @jdmichal. Tôi sẽ chỉnh sửa câu trả lời. –

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