java.util.Random 소스의 라인 294에 따르면
if ((n & -n) == n) // i.e., n is a power of 2
// rest of the code
왜 이런거야?
java.util.Random 소스의 라인 294에 따르면
if ((n & -n) == n) // i.e., n is a power of 2
// rest of the code
왜 이런거야?
(n & (n - 1)) == 0
도 작동합니다 (남은 비트가 없으면 처음에 최대 1 비트가 설정되어있는 경우 최하위 비트를 제거합니다).
답변:
(0 & -0) == 0
0은 2의 거듭 제곱이 아니기 때문에 설명이 완전히 정확 하지는 않습니다. 그것을 말하는 더 좋은 방법은
((n & -n) == n)
n이 2의 거듭 제곱이거나 2의 제곱 또는 0의 음수 일 때.
n이 2의 거듭 제곱이면 이진수의 n은 단일 1 다음에 0이 오는 것입니다. 2의 보수에서 -n은 역 + 1이므로 비트가 정렬됩니다.
n 0000100...000
-n 1111100...000
n & -n 0000100...000
왜이 일이 일어나는지 알아보기 위해 2의 보수를 역 + 1로 간주하고 -n == ~n + 1
n 0000100...000
inverse n 1111011...111
+ 1
two's comp 1111100...000
2의 보수를 얻기 위해 하나를 추가 할 때 하나를 끝까지 가지고 있기 때문입니다.
n이 2의 거듭 제곱이 아닌 경우 † 2의 보수가 해당 캐리로 인해 가장 높은 비트 세트를 갖지 않기 때문에 결과는 비트가 누락됩니다.
†-또는 2의 제곱의 0 또는 음수 ... 위에 설명 된대로.
Random.java
읽지 않은 것을 비판하지 않고 제목의 질문에 대답하고 있었다 .
n
이 무엇인지 알 수 없습니다 . 나는이 가정을 확인하지 않았지만 어떻게 든 a double
가 같은 방식으로 행동 할 것이라고 의심한다 .
n
이 질문에는 "java"태그가 있기 때문에 유형에 대해 꽤 좋은 경계를 둘 수 있습니다 . &
에 정의되지 않은 double
또는 float
Java로. 정수 유형 및 부울에만 정의됩니다. -
부울에 대해 정의되지 않았기 때문에 우리는 안전하게 n
적분을 추론 할 수 있습니다 .
때문에 2의 보수에 -n
있다 ~n+1
.
n
가 2의 거듭 제곱 이면 1 비트 만 설정됩니다. 그래서 ~n
그 비트를 제외한 모든 비트가 설정되었습니다. 하나를 추가하면 그 보장, 다시 특별 비트를 설정 n & (that thing)
같다 n
.
그 반대는 또한 해당 Java 소스의 이전 줄에서 0과 음수가 제외 되었기 때문에 사실입니다. 경우 n
다음 하나 개 이상의 비트 세트를 가지고 그 중 하나는 최고 이러한 비트입니다. 이 비트는 "흡수"할 더 낮은 클리어 비트가 있으므로에 의해 설정 되지 않습니다+1
.
n: 00001001000
~n: 11110110111
-n: 11110111000 // the first 0 bit "absorbed" the +1
^
|
(n & -n) fails to equal n at this bit.
이것이 사실 인 이유를 확인하려면 값을 비트 맵으로보아야합니다.
1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
따라서 두 필드가 모두 1 인 경우에만 1이 나옵니다.
이제 -n은 2의 보수를합니다. 이 모든 변화 0
에 1
그리고 1을 추가합니다.
7 = 00000111
-1 = NEG(7) + 1 = 11111000 + 1 = 11111001
하나
8 = 00001000
-8 = 11110111 + 1 = 11111000
00001000 (8)
11111000 (-8)
--------- &
00001000 = 8.
2의 거듭 제곱에 대해서만 (n & -n)
n이됩니다.
이것은 2의 거듭 제곱이 0의 긴 바다에서 단일 세트 비트로 표현되기 때문입니다. 부정은 1의 바다에서 정반대의 단일 0 (1이 있었던 지점) 을 산출합니다 . 1을 더하면 낮은 값이 0이있는 공간으로 이동합니다.
그리고 비트 및 (&)는 1을 다시 필터링합니다.
2의 보수 표현에서 2의 거듭 제곱에 대한 독특한 점은 n = 2 ^ k 인 k 번째 비트를 제외하고 모두 0 비트로 구성된다는 것입니다.
base 2 base 10
000001 = 1
000010 = 2
000100 = 4
...
2의 보수에서 음수 값을 얻으려면 모든 비트를 뒤집고 1을 더합니다. 2의 거듭 제곱의 경우, 이는 양수 값에있는 1 비트까지 포함하여 왼쪽에 1 묶음과 오른쪽에 0 묶음이 있음을 의미합니다.
n base 2 ~n ~n+1 (-n) n&-n
1 000001 111110 111111 000001
2 000010 111101 111110 000010
4 000100 111011 111100 000100
8 001000 110111 111000 001000
2 열과 4 열의 결과가 2 열과 동일하다는 것을 쉽게 알 수 있습니다.
이 차트에서 누락 된 다른 값을 살펴보면 이것이 2의 거듭 제곱 외에는 어떤 것도 유지하지 않는 이유를 알 수 있습니다.
n base 2 ~n ~n+1 (-n) n&-n
1 000001 111110 111111 000001
2 000010 111101 111110 000010
3 000011 111100 111101 000001
4 000100 111011 111100 000100
5 000101 111010 111011 000001
6 000110 111001 111010 000010
7 000111 111000 111001 000001
8 001000 110111 111000 001000
n & -n은 (n> 0 인 경우) 1 비트 만 설정되며 해당 비트는 n에서 최하위 설정 비트가됩니다. 2의 거듭 제곱 인 모든 숫자의 경우 최하위 세트 비트가 유일한 세트 비트입니다. 다른 모든 숫자에는 둘 이상의 비트 세트가 있으며 그 중 최하위 비트 만 결과에 설정됩니다.
2의 거듭 제곱과 2 의 보수 의 속성입니다 .
예를 들어, 8을 사용하십시오.
8 = 0b00001000
-8 = 0b11111000
2의 보수 계산 :
Starting: 0b00001000
Flip bits: 0b11110111 (one's complement)
Add one: 0b11111000
AND 8 : 0b00001000
2의 멱수를 들어, 단지 하나의 비트가 설정 될 것이다 첨가하면 N 발생할 수 있도록 제 2의 비트를 N 으로 설정되어야한다 (하나의 N에 들고 유지 번째 비트). 그런 다음 AND
두 개의 숫자가 있으면 원래의 숫자를 얻습니다.
2의 거듭 제곱이 아닌 숫자의 경우 다른 비트가 뒤집 히지 않으므로 AND
원래 숫자가 생성되지 않습니다.
간단히 말해서, n이 2의 거듭 제곱이면 한 비트 만 1로 설정되고 나머지 비트는 0으로 설정됩니다.
00000...00001 = 2 ^ 0
00000...00010 = 2 ^ 1
00000...00100 = 2 ^ 2
00000...01000 = 2 ^ 3
00000...10000 = 2 ^ 4
and so on ...
그리고 -n
2의 보수 이기 때문에 n
(즉, 1 인 유일한 비트는 그대로 남아 있고 해당 비트의 왼쪽에있는 비트는 1에 위치합니다. 이는 AND 연산자의 결과 &
가 0이 되므로 실제로 중요하지 않습니다. 두 비트 중 하나가 0 임) :
000000...000010000...00000 <<< n
&
111111...111110000...00000 <<< -n
--------------------------
000000...000010000...00000 <<< n