2010-04-27 62 views
8

Tôi đang cố gắng tối ưu hóa một số quy trình đóng gói và giải nén bit. Để thực hiện việc đóng gói, tôi cần tính toán số bit cần thiết để lưu trữ các giá trị số nguyên. Đây là mã hiện tại.Cách nhanh nhất để tính số lượng bit cần thiết để lưu trữ một số

if (n == -1) return 32; 
if (n == 0) return 1; 
int r = 0; 
while (n) 
{ 
    ++r; 
    n >>= 1; 
} 
return r; 
+1

Tôi hy vọng bạn không cố nén dữ liệu và đặt trước từng giá trị bằng số lượng bit trong giá trị. – Skizz

+1

Khi bạn viết "32", tôi đoán bạn có nghĩa là sizeof (int) * CHAR_BIT. Bạn có muốn mã của bạn hoạt động ở nơi sizeof (int) == 8 không? –

+1

Nếu bạn đang sử dụng >>, bạn thực sự muốn n được unsigned. –

Trả lời

5

Bạn đang tìm cách xác định số nguyên bản ghi 2 của một số (bộ l = bit cao nhất). Trang "Bit Twiddling Hacks" của Sean Anderson có một số phương pháp khác nhau, từ các bit đếm rõ ràng trong một vòng lặp đến các phiên bản sử dụng tra cứu bảng. Lưu ý rằng hầu hết các phương pháp được chứng minh sẽ cần phải được sửa đổi một chút để làm việc với các bit int-bit nếu kiểu di động đó quan trọng đối với bạn.

Chỉ cần chắc chắn rằng bất kỳ thay đổi bạn đang sử dụng để tìm ra các thiết lập bit cao nhất cần phải làm' trên một phiên bản unsigned số từ một việc thực hiện biên dịch có thể hoặc có thể không ký hiệu mở rộng hoạt động >> trên giá trị đã ký.

+1

Thậm chí không nhận ra những gì tôi đã cố gắng làm là tính toán cơ sở log 2. Kinda bỏ qua logarithms trong lớp Toán. Trang web đó có một số nội dung hữu ích. Cảm ơn –

+0

Liên kết đã bị hỏng! –

9

Không có khả năng sử dụng mã vạch ngược quét bit có sẵn trên hầu hết các kiến ​​trúc hiện đại. Nó được hiển thị dưới dạng intrinsic trong Visual C++.

Có thể, mã trong câu hỏi không cần xử lý cạnh trường hợp. Tại sao bạn cần một chút để lưu trữ 0? Trong mọi trường hợp, tôi sẽ bỏ qua các cạnh của vấn đề. Can đảm có thể được thực hiện một cách hiệu quả như sau:

if (n >> 16) { r += 16; n >>= 16; } 
if (n >> 8) { r += 8; n >>= 8; } 
if (n >> 4) { r += 4; n >>= 4; } 
if (n >> 2) { r += 2; n >>= 2; } 
if (n - 1) ++r; 
3

Bạn sẽ phải kiểm tra thời gian thực hiện để tìm các chi tiết, nhưng tôi đoán là làm 4 bit tại một thời điểm, và sau đó quay trở lại một chút tại một thời gian sẽ lam no nhanh hơn. Các hoạt động nhật ký có thể sẽ chậm hơn các phép toán logic/bit.

if (n < 0) return 32; 
int r = 0; 
while (n && 0x7FFFFFF0) { 
    r+=4; 
    n >>= 4; } 
while (n) { 
    r++; 
    n >>= 1; } 
return r; 
5

Những gì bạn đang cố gắng làm là tìm bit quan trọng nhất. Một số kiến ​​trúc có một hướng dẫn đặc biệt chỉ dành cho mục đích này. Đối với những người không sử dụng phương pháp tra cứu bảng.

Tạo một bảng gồm 256 mục nhập, trong đó mỗi phần tử xác định bit trên cao nhất.

Hoặc lặp qua từng byte trong số hoặc sử dụng một vài câu lệnh if để ngắt để tìm byte không phải thứ tự cao nhất.

Tôi sẽ cho phép bạn lấy phần còn lại từ đây.

+1

Trên CPU nhanh với RAM chậm (a PC!) Điều này có thể chậm hơn so với chỉ làm một vòng lặp for. Vòng lặp for sẽ liên tục trong vùng của một trăm chu kỳ đồng hồ trong khi tra cứu bộ nhớ có thể mất 10s của mili giây nếu dữ liệu cần được phân trang từ đĩa (và sau đó bạn đang làm rối bộ đệm để có hiệu ứng gõ). – Skizz

3

Thực hiện tìm kiếm nhị phân thay vì tìm kiếm tuyến tính.

if ((n >> 16) != 0) 
{ 
    r += 16; 
    n >>= 16; 
} 

if ((n >> 8) != 0) 
{ 
    r += 8; 
    n >>= 8;   
} 

if ((n >> 4) != 0) 
{ 
    r += 4; 
    n >>= 4;   
} 

// etc. 

Nếu phần cứng của bạn có bit-scan-reverse, cách tiếp cận nhanh hơn sẽ là viết thường trình của bạn bằng ngôn ngữ lắp ráp. Để giữ cho di động mã của bạn, bạn có thể làm

#ifdef ARCHITECTURE_WITH_BSR 
    asm // ... 
#else 
    // Use the approach shown above 
#endif 
1
number_of_bits = log2(integer_number) 

làm tròn đến số nguyên lớn hơn.

+4

Anh ấy muốn tối ưu hóa nó, không phải để làm cho nó đi chậm hơn ... –

+1

@Matteo, tất nhiên anh ta muốn tối ưu hóa mã nhưng tối ưu hóa nitty-picky này sẽ dẫn đến mã sai lầm. lấy log2 là một cách tiếp cận thanh lịch, sạch sẽ, có thể đọc và duy trì được. – Mahes

+1

@Mahes: câu hỏi nêu rõ "cách nhanh nhất" cho các thường trình đóng gói/giải nén bit là gì, có thể được gọi trong vòng lặp bên trong, nơi hiệu suất * là * quan trọng.Thay vì một số ít các lệnh dịch chuyển/bitwise, giải pháp này liên quan đến việc chuyển đổi một số nguyên thành dấu phẩy động (chậm), một số tra cứu bảng (có thể kích hoạt bộ nhớ cache)/tính toán chuỗi cắt ngắn (đối với nhật ký) và chuyển đổi trở lại int (một lần nữa, khá chậm). Malus điểm nếu nó là một nền tảng nhúng mà không có phần cứng FP, do đó, mọi hoạt động FP phải được mô phỏng trong phần mềm. –

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