Một số câu trả lời quá phức tạp ở đây. Kỹ thuật Debruin chỉ nên được sử dụng khi đầu vào đã là lũy thừa của hai, nếu không sẽ có một cách tốt hơn. Đối với sức mạnh của 2 đầu vào, Debruin là nhanh nhất tuyệt đối, thậm chí nhanh hơn _BitScanReverse
bất kỳ bộ xử lý nào mà tôi đã thử nghiệm. Tuy nhiên, trong trường hợp chung,_BitScanReverse
(hoặc bất cứ thứ gì nội tại được gọi trong trình biên dịch của bạn) là nhanh nhất (trên một số CPU nhất định, nó có thể được mã hóa vi mô).
Nếu chức năng nội tại không phải là một tùy chọn, thì đây là một giải pháp phần mềm tối ưu để xử lý các đầu vào chung.
u8 inline log2 (u32 val) {
u8 k = 0;
if (val > 0x0000FFFFu) { val >>= 16; k = 16; }
if (val > 0x000000FFu) { val >>= 8; k |= 8; }
if (val > 0x0000000Fu) { val >>= 4; k |= 4; }
if (val > 0x00000003u) { val >>= 2; k |= 2; }
k |= (val & 2) >> 1;
return k;
}
Lưu ý rằng phiên bản này không yêu cầu tra cứu Debruin ở cuối, không giống như hầu hết các câu trả lời khác. Nó tính toán vị trí tại chỗ.
Mặc dù vậy, bảng có thể được ưu tiên hơn, nếu bạn gọi nó liên tục đủ lần, nguy cơ bỏ lỡ bộ nhớ cache sẽ bị lu mờ bởi tốc độ tăng tốc của bảng.
u8 kTableLog2[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
u8 log2_table(u32 val) {
u8 k = 0;
if (val > 0x0000FFFFuL) { val >>= 16; k = 16; }
if (val > 0x000000FFuL) { val >>= 8; k |= 8; }
k |= kTableLog2[val]; // precompute the Log2 of the low byte
return k;
}
Điều này sẽ tạo ra thông lượng cao nhất trong số các câu trả lời phần mềm được đưa ra ở đây, nhưng nếu bạn chỉ thỉnh thoảng gọi nó, hãy thích một giải pháp không cần bảng như đoạn mã đầu tiên của tôi.