2010-06-29 28 views
21

Cách hiệu quả nhất để loại bỏ các bit xen kẽ từ một int 32 bit là gì? Đối với trường hợp cụ thể này, tôi chỉ quan tâm đến các bit lẻ, mặc dù tôi chắc chắn nó đơn giản để khái quát hóa bất kỳ giải pháp nào cho cả hai bộ. Ví dụ, tôi muốn chuyển đổi 0b01000101 thành 0b1011. Cách nhanh nhất là gì?Làm thế nào để tách rời các bit (UnMortonizing?)

EDIT:

Trong ứng dụng này, tôi có thể đảm bảo rằng các bit đều là 0. Tôi có thể tận dụng lợi thế của thực tế đó để cải thiện tốc độ hoặc giảm không gian?

Trả lời

32

Cho rằng bạn biết rằng tất cả các bit khác là 0 trong ứng dụng của bạn, bạn có thể làm điều đó như thế này:

x = (x | (x >> 1)) & 0x33333333; 
x = (x | (x >> 2)) & 0x0f0f0f0f; 
x = (x | (x >> 4)) & 0x00ff00ff; 
x = (x | (x >> 8)) & 0x0000ffff; 

Bước đầu tiên trông như thế này:

0a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0p x 
| 00a0b0c0d0e0f0g0h0i0j0k0l0m0n0o0 x >> 1 
    -------------------------------- 
= 0aabbccddeeffgghhiijjkkllmmnnoop x | (x >> 1) 
& 00110011001100110011001100110011 0x33333333 
    -------------------------------- 
= 00ab00cd00ef00gh00ij00kl00mn00op (x | (x >> 1)) & 0x33333333 

Sau đó, bước thứ hai hoạt động với hai bit cùng một lúc, v.v.

+0

đẹp. Đây chính xác là điều tôi đã nghĩ đến. – AShelly

+0

kiểm tra này nhanh hơn một bảng nhập 32 trên máy tính của tôi. – AShelly

+2

... và nếu bạn không biết rằng các bit lẻ là số không, hãy thực hiện 'x & = 0x55555555' trước – Bergi

2

Xét về tốc độ, bảng tra cứu rộng 16 bit với 2^32 mục sẽ khó đánh bại! Nhưng nếu bạn không có nhiều bộ nhớ để rảnh, bốn tra cứu trong một bảng 256-entry, cộng với một vài ca và AND để ghép chúng lại với nhau, có thể là một lựa chọn tốt hơn. Hoặc có lẽ điểm ngọt ở đâu đó ở giữa ... nó phụ thuộc vào tài nguyên bạn có sẵn và cách chi phí khởi tạo bảng tra cứu sẽ được phân bổ theo số lần tra cứu bạn cần thực hiện.

+0

Tôi chắc chắn không có nhiều bộ nhớ để rảnh rỗi - Tôi đang nhắm mục tiêu nền tảng được nhúng. Bảng nhập 256 có thể hoạt động. Tôi vẫn quan tâm đến một phương pháp thuật toán. – AShelly

+0

@AShelly: điểm bắt đầu sẽ là suy nghĩ về số lượng vị trí mà mỗi bit có khả năng sẽ phải "di chuyển" (dịch chuyển) vào vị trí mới. Ví dụ, bit 6 sẽ được dịch chuyển đúng 3 vị trí, bit 4 x 2 địa điểm, bit 2 x 1 địa điểm và bit 0 mà không cần dịch chuyển. Sau đó, phân hủy số lượng thay đổi đó thành số nhị phân. Điều này làm việc bởi vì dịch chuyển bởi, nói rằng, 3 nơi là giống như chuyển bằng 2 và sau đó một lần nữa bằng cách 1. Sử dụng một mặt nạ bit để chọn các bit cần phải được chuyển. Cách tiếp cận này có thể tốn kém hơn một bảng tra cứu nhỏ. – rwong

+0

trên nền tảng được nhúng, hãy thử bảng 16 lần và xử lý 4 bit cùng một lúc. – rwong

0

Tôi không chắc chắn như thế nào nhanh nó sẽ được, nhưng bạn có thể làm điều gì đó như

int a = 0b01000101; 
int b = 0; 
int i = 0; 
while (a > 0) { 
    b |= (a & 1) << i; 
    a >>= 2; 
} 

Trong đó sẽ kéo tất cả các bit lẻ tắt của a và đặt chúng trên b.

+2

bạn cần một i + + trong đó ở đâu đó. – AShelly

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