Boolean “(number & 1) == 0” này có nghĩa là gì?


79

Trên CodeReview, tôi đã đăng một đoạn mã đang hoạt động và yêu cầu các mẹo để cải thiện nó. Một phương thức tôi nhận được là sử dụng phương thức boolean để kiểm tra xem ArrayList có số chỉ số chẵn hay không (bắt buộc). Đây là mã đã được đề xuất:

private static boolean isEven(int number)
{
    return (number & 1) == 0;
}

Vì tôi đã làm phiền người dùng cụ thể đó để được trợ giúp rất nhiều, nên tôi quyết định đã đến lúc tôi làm phiền cộng đồng SO! Tôi không thực sự hiểu nó hoạt động như thế nào. Phương thức này được gọi và lấy kích thước của ArrayList làm tham số (tức là ArrayList có mười phần tử, number = 10).

Tôi biết một đơn &chạy so sánh cả số và 1, nhưng tôi đã bị lạc sau đó.

Theo cách tôi đọc nó, nó nói rằng trả về true nếu number == 01 == 0. Tôi biết điều đầu tiên không đúng và điều thứ hai rõ ràng không có ý nghĩa. Ai có thể giúp tôi?

Chỉnh sửa: Tôi có lẽ nên thêm rằng mã không hoạt động, trong trường hợp bất kỳ ai đang thắc mắc.


2
Có ai biết ai đã liên kết bài viết này với bài viết khác (không liên quan gì đến thứ này) không? Tôi có thể xóa nó bằng cách nào đó không?
Andrew Martin,

1
Chết tiệt này thực sự là thực sự thông minh!
cauon 16/02/13

2
Điều này đã được giới thiệu trên Twitter.
Jonathon Reinhart


1
@GrijeshChauhan Bạn có thể vui lòng giải thích thêm là làm thế nào điều này nhanh hơn number % 2 == 0??
Vrushank

Câu trả lời:


114

Hãy nhớ rằng "&" là một thao tác theo bit. Có thể bạn biết điều này, nhưng tôi không hoàn toàn rõ ràng dựa trên cách bạn đặt câu hỏi.

Nói như vậy, ý tưởng lý thuyết là bạn có một số int, có thể được biểu diễn bằng bit bởi một số chuỗi 1 và 0. Ví dụ:

...10110110

Trong hệ nhị phân, bởi vì nó là cơ số 2, bất cứ khi nào phiên bản bitwise của số kết thúc bằng 0, nó là chẵn và khi nó kết thúc bằng 1 thì nó là lẻ.

Do đó, thực hiện một chút & với 1 cho phần trên là:

...10110110 & ...00000001

Tất nhiên, đây là 0, vì vậy bạn có thể nói rằng đầu vào ban đầu là thậm chí.

Ngoài ra, hãy xem xét một số lẻ. Ví dụ, thêm 1 vào những gì chúng tôi đã có ở trên. Sau đó

...10110111 & ...00000001

Bằng 1, và do đó, không bằng không. Thì đấy.


13
Cảm ơn - lời giải thích của bạn làm cho nó rất rõ ràng. Cộng với bất kỳ câu trả lời nào kết thúc bằng Voila đều đáng được ủng hộ.
Andrew Martin

1
Có lẽ cũng nên biết về số âm trong câu trả lời này.
Alvin Wong

3
Ngoài ra, tôi có thể sửa đổi câu trả lời này để bao gồm thực tế rằng n%k == n&(k-1)đối với tất cả knhững gì là lũy thừa dương của 2. Nó có thể không phải là những gì người hỏi đã hỏi nhưng đó là một điều hữu ích để biết.
mượt mà

1
@fluffy không nói rằng nó sẽ không hoạt động, nhưng không phải ai cũng biết sự bổ sung của hai.
Alvin Wong

1
@fluffy không nên có loghoặc 2^ở đâu đó trong biểu thức đó?
Navin

67

Bạn có thể xác định số chẵn hoặc lẻ bằng bit cuối cùng trong biểu diễn nhị phân của nó:

1 -> 00000000000000000000000000000001 (odd)
2 -> 00000000000000000000000000000010 (even)
3 -> 00000000000000000000000000000011 (odd)
4 -> 00000000000000000000000000000100 (even)
5 -> 00000000000000000000000000000101 (odd)
6 -> 00000000000000000000000000000110 (even)
7 -> 00000000000000000000000000000111 (odd)
8 -> 00000000000000000000000000001000 (even)

& giữa hai số nguyên là toán tử AND theo bit:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

Vì vậy, nếu (number & 1) == 0true, phương tiện numbernày là chẵn.


Hãy giả sử rằng number == 6:

6 -> 00000000000000000000000000000110 (even)

     &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

1 -> 00000000000000000000000000000001

-------------------------------------

0 -> 00000000000000000000000000000000

và khi nào number == 7:

7 -> 00000000000000000000000000000111 (odd)

     &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

1 -> 00000000000000000000000000000001

-------------------------------------

1 -> 00000000000000000000000000000001

18

&là toán tử AND bitwise. &&là toán tử logic AND

Trong hệ nhị phân, nếu bit chữ số được đặt (tức là một) thì số đó là số lẻ.

Trong hệ nhị phân, nếu bit chữ số là 0, thì số đó là số chẵn.

(number & 1) là một phép thử bitwise AND của bit chữ số.

Một cách khác để làm điều này (và có thể kém hiệu quả hơn nhưng dễ hiểu hơn) là sử dụng toán tử mô-đun %:

private static boolean isEven(int number)
{
    if (number < 0)
       throw new ArgumentOutOfRangeException();

    return (number % 2) == 0;
}

2
&cũng logic AND. &&ngắn mạch trong khi &không.
Steve Kuo

5
number % 2không giống như number & 1if numberlà tiêu cực.
dan04, 16/02/13

4
nếu bạn đang bị vượt qua một độ dài âm, thì bạn gặp vấn đề lớn hơn! ;)
Mitch Wheat

4
@RyanAmos "Lặp lại từng bit?" Bitwise AND là một thao tác duy nhất trong mọi CPU mà tôi từng thấy - đây là một trong những thao tác dễ thực hiện song song nhất.
mượt mà

2
@MitchWheat Không có lý do gì để ném vào number < 0trường hợp này - trong khi số âm lẻ ở mod 2 là -1, mod 2 chẵn vẫn là 0.
fluffy

8

Biểu thức này có nghĩa là "số nguyên đại diện cho một số chẵn".

Đây là lý do tại sao: biểu diễn nhị phân của số thập phân 100000000001. Tất cả các số lẻ đều kết thúc bằng 1nhị phân (điều này rất dễ xác minh: giả sử biểu diễn nhị phân của số không kết thúc bằng 1; khi đó nó bao gồm các lũy thừa khác 0 của hai, luôn là số chẵn). Khi bạn thực hiện một phép nhị phân ANDvới một số lẻ, kết quả là 1; khi bạn thực hiện một nhị phân ANDvới một số chẵn, kết quả là 0.

Đây từng là phương pháp ưa thích để quyết định số lẻ / chẵn vào thời điểm mà các trình tối ưu hóa kém đến không tồn tại và các %toán tử yêu cầu số chu kỳ gấp hai mươi lần số chu kỳ được thực hiện bởi một &toán tử. Ngày nay, nếu bạn làm như vậy number % 2 == 0, trình biên dịch có thể tạo ra mã thực thi nhanh như (number & 1) == 0hiện tại.


5

Toán tử đơn &có nghĩa là bit-khôn ngoan không so sánhand

Vì vậy, mã này kiểm tra xem đầu tiên bit(ít quan trọng nhất / đúng nhất) có được đặt hay không, cho biết nếu số đó có oddhay không; bởi vì tất cả các số lẻ sẽ kết thúc bằng 1bit ít quan trọng nhất, ví dụ:xxxxxxx1


Lưu ý rằng một đơn &có thể được sử dụng như một logic andnếu bạn muốn giữ lại tác dụng phụ từ ngữ nhưf(x) & g(x)
Navin

4

&là một ANDhoạt động bitwise .

Đối với số = 8:

  1000
  0001
& ----
  0000

Kết quả là như vậy (8 & 1) == 0. Đây là trường hợp của tất cả các số chẵn, vì chúng là bội số của 2 và chữ số nhị phân đầu tiên từ bên phải luôn là 0. 1 có giá trị nhị phân là 1 với các số 0 đứng đầu, vì vậy khi chúng ta đặt ANDnó với một số chẵn, chúng ta sẽ bỏ với 0.


3

Các &nhà điều hành trong Java là Bitwise-và điều hành. Về cơ bản, (number & 1)thực hiện một chút-và giữa number1. Kết quả là 0 hoặc 1, tùy thuộc vào việc nó chẵn hay lẻ. Sau đó, kết quả được so sánh với 0 để xác định xem nó có chẵn hay không.

Đây là trang mô tả các hoạt động bitwise .


3

Nó đang thực hiện một nhị phân và so với 1, trả về 0 nếu bit quan trọng nhất không được đặt

cho ví dụ của bạn

00001010 (10)

00000001 (1)

===========

00000000 (0)


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.