2013-04-11 31 views
14

Nếu tôi có một bitmask cơ bản ...bitmask: làm thế nào để xác định nếu chỉ có một bit được thiết lập

cat = 0x1; 
dog = 0x2; 
chicken = 0x4; 
cow = 0x8; 

// OMD has a chicken and a cow 
onTheFarm = 0x12; 

... làm thế nào tôi có thể kiểm tra nếu chỉ có một động vật (ví dụ: một bit) được thiết lập?

Giá trị của onTheFarm phải là 2 n, nhưng làm cách nào tôi có thể kiểm tra xem chương trình đó (tốt nhất là trong Javascript)?

+0

Khám phá [câu hỏi này] (http://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer). Không phải là javascript cụ thể, nhưng thú vị. –

+0

Cảm ơn Rob, chỉ tìm thấy điều này (có vẻ nhanh hơn một chút) http://stackoverflow.com/questions/1053582/how-does-this-bitwise-operation-check-for-a-power-of-2 – Tim

+2

Chỉ cần FYI, 'OMD' = [' Old MacDonald'] (https://en.wikipedia.org/wiki/Old_MacDonald_Had_a_Farm). – rvighne

Trả lời

9

Bạn có thể đếm số lượng các bit được đặt trong một giá trị số nguyên không âm với mã này (thích nghi với JavaScript từ this answer):

function countSetBits(i) 
{ 
    i = i - ((i >> 1) & 0x55555555); 
    i = (i & 0x33333333) + ((i >> 2) & 0x33333333); 
    return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; 
} 

Nó sẽ hiệu quả hơn nhiều so với việc kiểm tra từng bit riêng lẻ. Tuy nhiên, nó không hoạt động nếu bit dấu được đặt trong i.

EDIT (tất cả tín dụng để bình luận chóp của):

function isPowerOfTwo(i) { 
    return i > 0 && (i & (i-1)) === 0; 
} 
+1

Chà, điều đó khá tốt. Nhìn vào đó, tôi tìm thấy [tham chiếu này] (http://aggregate.org/MAGIC/#Is%20Power%20of%202) cho câu hỏi cụ thể này, và nó trông thậm chí còn tốt hơn! – Pointy

2

Bạn phải kiểm tra từng chút một, với một hàm nhiều hay ít như thế này:

function p2(n) { 
    if (n === 0) return false; 
    while (n) { 
    if (n & 1 && n !== 1) return false; 
    n >>= 1; 
    } 

    return true; 
} 

Một số CPU bộ giảng dạy đã bao gồm một "đếm thiết lập bit" hoạt động (CDC Cyber ​​phim cổ trang là một) . Nó rất hữu ích cho một số cấu trúc dữ liệu được thực hiện như các bộ sưu tập bit. Nếu bạn đã có một tập hợp được thực hiện như một chuỗi các số nguyên, với các vị trí bit tương ứng với các phần tử của kiểu dữ liệu được thiết lập, thì việc nhận được số lượng thẻ bao gồm đếm bit.

chỉnh sửa wow nhìn vào câu trả lời Ted Hopp của tôi stumbled trên này:

function p2(n) { 
    return n !== 0 && (n & (n - 1)) === 0; 
} 

Đó là từ this awesome collection of "tricks". Những điều như vấn đề này là lý do chính đáng để nghiên cứu lý thuyết số :-)

0

Nếu bạn đang tìm kiếm để xem nếu chỉ một chút đơn được thiết lập, bạn có thể tận dụng lợi thế của logarithms, như sau:

var singleAnimal = (Math.log(onTheFarm)/Math.log(2)) % 1 == 0; 

Math.log(y)/Math.log(2) tìm số x trong 2^x = yx % 1 cho chúng tôi biết nếu x là một số nguyên. x sẽ chỉ là một số nguyên nếu một bit được đặt và do đó, chỉ có một động vật được chọn.

+1

Mờ lờ bỏ vòng lặp điểm nổi, bạn sẽ kết luận rằng (1 << 29) sẽ có nhiều hơn một bộ: 'console.log ((Math.log (1 << 29)/Math.log (2))% 1) 'in 3.552713678800501e-15 trên máy của tôi. –

+0

Thú vị. Tôi cho rằng việc sử dụng 'log' nói chung sẽ kém hiệu quả hơn các kỹ thuật khác được nêu ra như là câu trả lời.Biết cách nào để xử lý lỗi roundoff floating point? – cmptrgeekken

+0

Không phải cho vấn đề này. Bạn có thể đọc tổng quan về các vấn đề trong [bài viết này] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html). Nó khá nặng về kỹ thuật, nhưng đáng để đấu tranh thông qua nếu bạn muốn có một sự hiểu biết vững chắc về những gì đang xảy ra dưới mui xe với điểm nổi. Phiên bản TL; DR là: mọi hoạt động điểm động (thậm chí chỉ đơn giản là đại diện cho một số) đều có lỗi; thiết kế mã của bạn cho phù hợp. –

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