2012-03-22 24 views
9

Nếu tôi có các mảng:là gì cách nhanh nhất để làm một sự thay đổi chút tròn ngay trên một mảng byte

{01101111,11110000,00001111} // {111, 240, 15} 

Kết quả cho một sự thay đổi 1 chút là:

{10110111,11111000,00000111} // {183, 248, 7} 

Kích thước mảng không cố định và việc dịch chuyển sẽ từ 1 đến 7. Hiện tại tôi có mã sau (hoạt động tốt):

private static void shiftBitsRight(byte[] bytes, final int rightShifts) { 
    assert rightShifts >= 1 && rightShifts <= 7; 

    final int leftShifts = 8 - rightShifts; 

    byte previousByte = bytes[0]; // keep the byte before modification 
    bytes[0] = (byte) (((bytes[0] & 0xff) >> rightShifts) | ((bytes[bytes.length - 1] & 0xff) << leftShifts)); 
    for (int i = 1; i < bytes.length; i++) { 
     byte tmp = bytes[i]; 
     bytes[i] = (byte) (((bytes[i] & 0xff) >> rightShifts) | ((previousByte & 0xff) << leftShifts)); 
     previousByte = tmp; 
    } 
} 

Có cách nào nhanh hơn để đạt được điều này hơn cách tiếp cận hiện tại của tôi không?

+3

Tôi nghĩ rằng việc nhóm vào 'lâu dài đầu tiên sẽ có lợi cho hiệu suất. –

+0

Nếu điều này là dành cho đồ họa, một tùy chọn khác để suy nghĩ là sử dụng định dạng được mã hóa theo thời lượng. Sau đó, chuyển dịch sẽ không phải thay đổi tất cả độ dài chạy ở giữa dòng. – BitBank

+1

'long' có thể cải thiện hiệu suất, nhưng nó sẽ thay đổi từ máy này sang máy khác. (Đôi khi 'int' sẽ tốt hơn.) –

Trả lời

4

Cách duy nhất để tìm hiểu là với đánh giá kỹ lưỡng điểm chuẩn và triển khai nhanh nhất sẽ thay đổi từ nền tảng sang platfrm. Sử dụng công cụ như Caliper nếu bạn thực sự cần tối ưu hóa điều này.

+3

Downvoters, giải thích? (Tôi sẽ rất ngạc nhiên nếu có bất kỳ câu trả lời chung nào cho câu hỏi của OP cụ thể hơn câu hỏi này.) –

+0

+1, hoàn toàn đúng –

0

Bạn có thể khái quát này để chờ đợi và nhiều hơn một chút thay đổi nếu bạn thích

// for a 1-bit rightshift: 
// first rotate each byte right by one 
for (i = 0; i < n; i++) b[i] = rotr(b[i], 1); 
// get rightmost bit 
bit = b[n-1] & 0x80; 
// copy high order bit from adjacent byte 
for (i = n; --i >= 1;){ 
    b[i] &= 0x7f; 
    b[i] |= (b[i-1] & 0x80); 
} 
// put in the rightmost bit on the left 
b[0] = (b[0] & 0x7f) | bit; 

giả rotr được định nghĩa.

1

Một trong những điều bạn có thể làm là thay thế (byte[a]&0xff)>>b với byte[a]>>>b

Ngoài ra, bạn không cần &0xff khi bạn đang rời chuyển.

Mặc dù điều đó có thể không quan trọng, hoặc thêm cuối cùng vào tmp hoặc di chuyển tuyên bố ra khỏi vòng lặp có thể giúp một chút.

Một điều có thể thử là:

int tmp=bytes[bytes.length-1]; 
for (int i = bytes.length-2; i >=0; i--) { 
    tmp=(tmp<<8)|bytes[i]; 
    bytes[i] = (byte) (tmp>>>rightShifts); 
} 

Sau đó, bạn giải quyết byte [bytes.length-1] sau đó.

Vòng lặp ngược đó cũng có thể hữu ích nếu bạn mê tín dị đoan. Tôi đã nhìn thấy nó hoạt động trước đây.

Phân tích vòng lặp mỗi lần vượt qua:

của bạn: 3 bài tập, hai ca, một hoặc một diễn viên.

mỏ: 2 bài tập, hai ca, một hoặc một diễn viên.

+0

'(byte [a] & 0xff) >> b' và' byte [a] >>> b' không tương đương! Trong phần trước, phía bên trái được nâng lên 'int' sau khi loại bỏ các byte cao tạo ra kết quả mong muốn. Sau đó, chương trình khuyến mãi xảy ra, sau đó là một sự thay đổi không dấu để các bit ở bên trái của 'a' sẽ là bit dấu của' a', sau đó là 'b' số 0. –

0

Sử dụng ByteBuffer.wrap để có được một bộ đệm mà kết thúc tốt đẹp byte[] của bạn và sau đó sử dụng ByteBuffer.asLongBuffer() để có được một cái nhìn cho phép bạn trích xuất và thao tác long s theo đề nghị của @NiklasB. do đó tận dụng khả năng của phần cứng để thay đổi các khối bit lớn hơn.

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