비트 연산자는 피연산자를 32비트(0과 1)의 시퀀스로 해석합니다. 이들은 숫자의 이진 표현을 사용하여 연산을 수행하고 그 결과로 새로운 32비트 시퀀스(숫자)를 반환합니다.
이 장은 고급 프로그래밍 지식이 필요하고 그다지 중요하지 않으므로 처음 읽을 때는 건너뛰고 나중에 비트 연산자의 작동 방식을 이해하고 싶을 때 다시 읽어도 됩니다.
32비트 부호 정수 형식
JavaScript의 비트 연산자는 이진 표현으로 32비트 정수를 처리합니다.
이 표현은 “32비트 부호 있는 정수, 가장 왼쪽의 가장 중요한 비트, 2의 보수”라고 합니다.
숫자가 내부적으로 어떻게 구조화되는지 자세히 살펴보겠습니다. 이는 숫자에 대한 비트 연산을 위해 알아야 할 사항입니다.
- 여러분은 이미 이진수 체계가 무엇 인지 알고 계시기를 바랍니다 . 비트 연산을 논의할 때, 우리는 32비트로 구성된 숫자의 이진 표현에 대해 논의할 것입니다.
- 왼쪽에서 가장 중요한 부분 은 가장 일반적인 숫자 표기 순서(가장 높은 숫자에서 가장 낮은 숫자 순)에 대한 학명입니다. 이 경우, 더 높은 숫자가 누락되면 해당 비트는 0과 같습니다.이진법에서 숫자를 표현하는 예:
a = 0; // 00000000000000000000000000000000 a = 1; // 00000000000000000000000000000001 a = 2; // 00000000000000000000000000000010 a = 3; // 00000000000000000000000000000011 a = 255;// 00000000000000000000000011111111
각 숫자는 정확히 32비트로 구성되어 있습니다. - 2의 보수는 음수를 뒷받침하는 방법을 일컫는 이름입니다.주어진 숫자의 역수인 숫자의 이진 형태(예:
5
)-5
는 모든 비트를 반전하고 1을 더하여 얻습니다.즉, 0은 1로, 1은 0으로 바뀌고 숫자에 더해집니다1
. 결과적으로 같은 숫자의 내부 표현이 나오지만, 빼기 기호가 붙습니다.예를 들어, 다음은 숫자입니다314
.00000000000000000000000100111010
를 얻으려면-314
첫 번째 단계는 숫자의 비트를 반전하는 것입니다.0
를1
,1
로 바꾸세요0
.11111111111111111111111011000101
두 번째 단계는 일반적인 이진수 덧셈을 사용하여 결과 이진수에 1을 더하는 것입니다11111111111111111111111011000101 + 1 = 11111111111111111111111011000110
.그래서 우리는 다음을 얻었습니다:-314 = 11111111111111111111111011000110
2의 보수 원리는 모든 이진 표현을 두 개의 집합으로 나눕니다. 가장 왼쪽의 비트가 같으면0
숫자는 양수이고, 같지 않으면1
숫자는 음수입니다. 따라서 이 비트를 부호 비트 라고 합니다 .
운영자 목록
다음 표에는 모든 비트 연산자가 나열되어 있습니다. 아래에서 연산자에 대해 더 자세히 설명하겠습니다.
연산자 | 용법 | 설명 |
---|---|---|
비트 단위 AND | a & b | 피연산자의 해당 비트가 1인 결과 비트에 1을 넣습니다. |
비트 단위 OR | a | b | 피연산자의 해당 비트 중 적어도 하나가 1인 결과의 비트에 1을 넣습니다. |
비트 단위 배타적 OR (XOR) | a ^ b | 해당 피연산자 비트 중 하나만 1인(둘 다는 아님) 결과 비트에 1을 넣습니다. |
비트 단위 NOT | ~a | 피연산자의 각 비트를 반대 값으로 바꿉니다. |
왼쪽 쉬프트 | a << b | 이진 표현을 왼쪽으로 비트 a 만큼 이동하고 오른쪽에 0을 추가합니다.b |
오른쪽 이동, 부호 이동 | a >> b | 이진 표현을 오른쪽으로 비트 a 만큼 이동하고, 이동된 비트를 삭제합니다.b |
0 채우기로 오른쪽 이동 | a >>> b | 이진 표현을 오른쪽으로 비트 a 만큼 이동하고, 이동된 비트를 버리고 왼쪽에 0을 추가합니다.b |
비트 연산자는 다음과 같이 작동합니다.
- 피연산자는 비트의 시퀀스로 표현되는 32비트 정수로 변환됩니다. 소수 부분이 있으면 삭제합니다.
- 이진 연산자의 경우, 첫 번째 피연산자의 각 비트는 두 번째 피연산자의 해당 비트와 함께 고려됩니다. 즉, 첫 번째 비트는 첫 번째 비트와, 두 번째 비트는 두 번째 비트와 함께 고려됩니다. 연산자는 각 비트 쌍에 적용되어 해당 결과 비트를 생성합니다.
- 결과적으로 나오는 비트 시퀀스는 일반 숫자로 해석됩니다.
예제를 통해 연산자가 어떻게 작동하는지 살펴보겠습니다.
도우미 함수 parseInt, toString
이 글의 예제를 더 쉽게 사용하기 위해 콘솔에서 무언가를 테스트하려면 두 가지 함수가 필요합니다.
parseInt("11000", 2)
– 숫자의 이진 표현을 가진 문자열을 숫자로 변환합니다.n.toString(2)
n
– 2차원 시스템의 숫자에 대한 레코드를 문자열로 수신합니다 .
예를 들어:
let access = parseInt("11000", 2); // получаем число из строки
alert( access ); // 24, число с таким 2-ным представлением
let access2 = access.toString(2); // обратно двоичную строку из числа
alert( access2 ); // 11000
이것이 없다면 이진법으로 변환하거나 이진법에서 이진법으로 변환하는 것은 훨씬 불편할 것입니다. 이에 대해서는 숫자 장에서 더 자세히 논의됩니다 .
& (비트 단위 AND)
각 비트 쌍에 대해 AND 연산을 수행합니다.
두 비트가 모두 하나일 a & b
때만 결과 가 하나입니다 .a
b
진리표 &
:
a | b | a & b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
예:
9 (по осн. 10)
= 00000000000000000000000000001001 (по осн. 2)
14 (по осн. 10)
= 00000000000000000000000000001110 (по осн. 2)
--------------------------------
14 & 9 (по осн. 10)
= 00000000000000000000000000001000 (по осн. 2)
= 8 (по осн. 10)
| (비트 단위 OR)
각 비트 쌍에 대해 OR 연산을 수행합니다. a | b
최소한 하나의 비트가 1이면 결과 는 1 a,b
입니다.
진리표 |
:
a | b | a | b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
예:
9 (по осн. 10)
= 00000000000000000000000000001001 (по осн. 2)
14 (по осн. 10)
= 00000000000000000000000000001110 (по осн. 2)
--------------------------------
14 | 9 (по осн. 10)
= 00000000000000000000000000001111 (по осн. 2)
= 15 (по осн. 10)
^ (배타적 OR)
각 비트 쌍에 대해 배타적 OR 연산을 수행합니다.
a
배타적 논리합은 둘 중 하나만 b
만족하는 경우에만 1이고 , 둘 다는 만족하는 경우에는 1이 아닙니다 .a=1
b=1
a=b=1
배타적 OR에 대한 진리표:
a | b | a ^ b |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
보시다시피, 왼쪽 1
이나 오른쪽에 모두 있는 경우에는 1을 주지만 1
, 둘 다 있는 경우에는 1을 주지 않습니다. 그래서 이것을 “배타적 논리합”이라고 부릅니다.
예:
9 (по осн. 10)
= 00000000000000000000000000001001 (по осн. 2)
14 (по осн. 10)
= 00000000000000000000000000001110 (по осн. 2)
--------------------------------
14 ^ 9 (по осн. 10)
= 00000000000000000000000000000111 (по осн. 2)
= 7 (по осн. 10)
암호화에서의 배타적 OR
XOR은 연산이 완전히 가역적이기 때문에 암호화에 사용될 수 있습니다. 같은 인수로 배타적 OR을 두 번 적용하면 원래 숫자가 생성됩니다.
즉, 공식은 맞습니다: a ^ b ^ b == a
.
바샤가 페티아에게 비밀 정보를 전달하고 싶어하게 하세요 data
. 이 정보는 미리 숫자로 변환됩니다. 예를 들어 문자열은 일련의 문자 코드로 해석됩니다.
바샤와 페티아는 숫자형 암호화 키에 대해 미리 합의합니다 key
.
연산:
- 바샤는 이진 표현을 취하고
data
연산을 수행합니다data ^ key
. 필요한 경우, 각 부분에 대해 비트 OR을 수행할 수 있도록data
동일한 길이의 부분으로 나눕니다 . JavaScript에서 이 연산자는 32비트 정수를 다루므로 이러한 숫자의 시퀀스로 분할해야 합니다.key
^
^
data
- 결과는
data ^ key
암호화되어 Petya로 전송됩니다.
예를 들어, data
다음 숫자가 9
이고 키 key
가 라고 가정 해 보겠습니다 1220461917
.
Данные: 9 в двоичном виде
00000000000000000000000000001001
Ключ: 1220461917 в двоичном виде
01001000101111101100010101011101
Результат операции 9 ^ key:
01001000101111101100010101010100
Результат в 10-ной системе (шифровка):
1220461908
- 다음 암호화 번호를 받은 Petya는
1220461908
동일한 작업을 적용합니다^ key
. - 결과는 원래의 숫자가 됩니다
data
.
우리의 경우:
Полученная шифровка в двоичной системе:
9 ^ key = 1220461908
01001000101111101100010101010100
Ключ: 1220461917 в двоичном виде:
01001000101111101100010101011101
Результат операции 1220461908 ^ key:
00000000000000000000000000001001
Результат в 10-ной системе (исходное сообщение):
9
물론, 이러한 암호화는 주파수 분석 및 기타 암호 해독 방법에 취약하므로 현대 알고리즘은 ^
보다 복잡한 다단계 방식의 중요한 부분 중 하나로 XOR 연산을 사용합니다.
~ (비트 단위 NOT)
각 비트에 대해 NOT 연산을 수행하여 해당 비트를 역수로 바꿉니다.
NOT에 대한 진리표:
a | ~a |
---|---|
0 | 1 |
1 | 0 |
예:
9 (по осн. 10)
= 00000000000000000000000000001001 (по осн. 2)
--------------------------------
~9 (по осн. 10)
= 11111111111111111111111111110110 (по осн. 2)
= -10 (по осн. 10)
음수의 내부 표현으로 인해 ~n == -(n+1)
.
예를 들어:
alert( ~3 ); // -4
alert( ~-1 ); // 0
<< (비트 왼쪽으로 이동)
비트 이동 연산자는 두 개의 피연산자를 사용합니다. 첫 번째는 이동할 숫자이고, 두 번째는 첫 번째 피연산자에서 이동할 비트 수입니다.
연산자는 <<
첫 번째 피연산자를 지정된 비트 수만큼 왼쪽으로 이동합니다. 초과 비트는 삭제되고 0비트가 오른쪽에 추가됩니다.
예를 들어, 다음과 9 << 2
같은 결과가 나옵니다 36
.
9 (по осн.10)
= 00000000000000000000000000001001 (по осн.2)
--------------------------------
9 << 2 (по осн.10)
= 00000000000000000000000000100100 (по осн.2)
= 36 (по осн.10)
이 연산은 << 2
왼쪽의 두 개의 0 비트를 이동시키고 버리고, 오른쪽에 두 개의 새로운 0 비트를 추가합니다.
왼쪽으로 이동하는 것은 2를 곱하는 것과 거의 같습니다.
비트 이동은 << N
일반적으로 2를 곱하는 것과 같은 효과를 갖습니다 N
. 예를 들어:
alert( 3 << 1 ); // 6, умножение на 2
alert( 3 << 2 ); // 12, умножение на 2 два раза
alert( 3 << 3 ); // 24, умножение на 2 три раза
물론, 비트 연산자는 32비트 숫자에서만 작동하므로 이러한 “곱셈”의 상한은 제한됩니다.
alert
(
10000000000
<<
1
)
;
// -1474836480, отброшен крайний-левый бит
alert(10000000000 * 2); // 20000000000, обычное умножение
>> (오른쪽 비트 이동, 캐리 부호)
이 연산자는 비트를 오른쪽으로 이동하고, 초과된 비트는 삭제합니다. 이 경우, 가장 왼쪽 비트의 복사본이 왼쪽에 추가됩니다.
숫자의 부호(가장 왼쪽 비트로 표현)는 변경되지 않습니다. 새로운 가장 왼쪽 비트가 원래 숫자와 동일한 값을 갖기 때문입니다.
그래서 그는 “표지판 전달자”라고 불립니다.
예를 들어, 다음과 9 >> 2
같은 결과가 나옵니다 2
.
9 (по осн.10)
= 00000000000000000000000000001001 (по осн.2)
--------------------------------
9 >> 2 (по осн.10)
= 00000000000000000000000000000010 (по осн.2)
= 2 (по осн.10)
연산은 >> 2
오른쪽으로 이동하고 오른쪽 두 비트를 버리고 01
첫 번째 비트의 사본 두 개를 왼쪽에 추가했습니다 00
.
마찬가지로, -9 >> 2
다음을 제공합니다 -3
.
-9 (по осн.10)
= 11111111111111111111111111110111 (по осн.2)
--------------------------------
-9 >> 2 (по осн.10)
= 11111111111111111111111111111101 (по осн.2) = -3 (по осн.10)
여기서 연산은 >> 2
오른쪽으로 이동하고 오른쪽 두 비트를 버리고 11
첫 번째 비트의 사본 두 개를 왼쪽에 추가합니다 11
. , 가장 왼쪽의 (부호) 비트가 값을 유지하므로 숫자의 부호는 유지됩니다 1
.
오른쪽 이동은 정수를 2로 나누는 것과 거의 같습니다.
비트 이동은 >> N
일반적으로 정수를 2로 나누는 것과 같은 결과를 가져옵니다 N
.
alert( 100 >> 1 ); // 50, деление на 2
alert( 100 >> 2 ); // 25, деление на 2 два раза
alert( 100 >> 3 ); // 12, деление на 2 три раза, целая часть от результата
>>> (0 채우기로 오른쪽으로 이동)
이 연산자는 첫 번째 피연산자의 비트를 오른쪽으로 이동합니다. 오른쪽의 여분의 비트는 삭제됩니다. 0비트는 왼쪽에 추가됩니다.
부호 비트는 0이 되므로 결과는 항상 양수입니다.
음수가 아닌 숫자의 경우 0 패딩을 사용한 오른쪽 이동 >>>
과 부호 캐리를 사용한 오른쪽 이동은 >>
동일한 결과를 제공합니다. 두 경우 모두 왼쪽에 0이 추가됩니다.
음수의 경우 작업 결과가 다릅니다. 예를 들어, (gives ) 와 대조적으로 -9 >>> 2
will give 는 다음과 같습니다 .1073741821
-9 >> 2
-3
-9 (по осн.10)
= 11111111111111111111111111110111 (по осн.2)
--------------------------------
-9 >>> 2 (по осн.10)
= 00111111111111111111111111111101 (по осн.2)
= 1073741821 (по осн.10)
비트 연산자 사용
비트 연산자는 거의 사용되지 않지만, 여전히 사용됩니다.
여기서 다룰 비트 연산자의 사용 사례는 JavaScript에서 사용되는 대부분의 사례를 차지합니다.
조심하세요, 우선순위!
JavaScript에서 비트 연산자 ^
, &
, 는 |
비교 후에 수행됩니다 ==
.
예를 들어, 비교에서는 a == b^0
비교가 먼저 수행되고 a == b
, 그 다음에 연산이 수행됩니다. ^0
마치 괄호가 있는 것처럼 말입니다 (a == b)^0
.
이것은 보통 우리가 원하는 것이 아니다. 원하는 순서를 보장하려면 괄호를 사용해야 합니다: a == (b^0)
.
마스크
이 예제에서는 스크립트가 사용자를 대상으로 동작한다고 가정해 보겠습니다.
그들은 프로젝트에서 서로 다른 역할을 할 수 있습니다.
Гость
Редактор
Админ
각 역할은 기사 및 사이트 기능에 대한 액세스 권한 수에 해당합니다.
예를 들어, Гость
그는 사이트의 기사를 볼 수만 있지만 Редактор
편집할 수도 있습니다.
이런 것:
사용자 | 기사보기 | 기사 변경 | 제품보기 | 상품 교환 | 권리 관리 |
---|---|---|---|---|---|
손님 | 예 | 아니요 | 예 | 아니요 | 아니요 |
편집자 | 예 | 예 | 예 | 예 | 아니요 |
관리자 | 예 | 예 | 예 | 예 | 예 |
1
“예” 대신 “아니요” 대신 – 를 입력하면 0
각 액세스 세트는 숫자로 설명됩니다.
사용자 | 기사보기 | 기사 변경 | 제품보기 | 상품 교환 | 권리 관리 | 10진법에서는 |
---|---|---|---|---|---|---|
손님 | 1 | 0 | 1 | 0 | 0 | = 20 |
편집자 | 1 | 1 | 1 | 1 | 0 | = 30 |
관리자 | 1 | 1 | 1 | 1 | 1 | = 31 |
마지막 열에는 액세스 문자열을 이진수 형태로 읽으면 얻어지는 10진수가 들어 있습니다.
예를 들어, 게스트 액세스 10100 = 20
.
이러한 접근 방식의 해석을 통해 많은 정보를 하나의 숫자로 “압축”할 수 있습니다. 이렇게 하면 메모리가 절약되고, 게다가 편리합니다. 메모리를 절약하는 것 외에도 이 값을 사용하면 방문자가 주어진 접근 조합을 가지고 있는지 확인하기가 매우 쉬워집니다 !
이를 위해 2번째 시스템에서 각 접근이 어떻게 별도로 표현되는지 살펴보겠습니다.
- 권리 관리에만 해당하는 접근: ( 이 접근에 해당하는 위치를
00001 (=1)
제외한 모든 위치는 0입니다 ).1
- 상품 교환을 위해서만 접근 가능합니다:
00010 (=2)
. - 제품 보기에만 접근 가능:
00100 (=4)
. - 기사 편집을 위해서만 접근 가능:
01000 (=8)
. - 기사 보기에만 접근이 제한됨:
10000 (=16)
.
동시에 기사를 보거나 편집할 수 있는 권한은 1
해당 위치에 .이진수가 들어 있는 것입니다 access = 11000
.
일반적으로 액세스는 상수로 지정됩니다.
const ACCESS_ADMIN = 1; // 00001
const ACCESS_GOODS_EDIT = 2; // 00010
const ACCESS_GOODS_VIEW = 4; // 00100
const ACCESS_ARTICLE_EDIT = 8; // 01000
const ACCESS_ARTICLE_VIEW = 16; // 10000
이러한 상수에서 원하는 접근 조합은 다음 연산을 사용하여 얻을 수 있습니다 |
.
const guest = ACCESS_ARTICLE_VIEW | ACCESS_GOODS_VIEW; // 10100
const editor = guest | ACCESS_ARTICLE_EDIT | ACCESS_GOODS_EDIT; // 11110
const admin = editor | ACCESS_ADMIN; // 11111
이제 필요한 접근 권한이 있는지 확인하려면 (예: 권한 관리) 해당 상수와 함께 editor
비트 AND 연산자( )를 적용하면 됩니다 .&
0이 아닌 결과는 액세스가 가능하다는 것을 의미합니다.
alert(editor & ACCESS_ADMIN); // 0, доступа нет
alert(editor & ACCESS_ARTICLE_EDIT); // 8, доступ есть
이 검사는 AND 연산자가 1
두 피연산자 모두에 가 포함된 결과 위치에 를 배치하기 때문에 작동합니다 1
.
여러 가지 접근 방법 중 하나를 선택할 수 있습니다.
예를 들어, 제품을 보거나 변경할 수 있는 권한이 있는지 확인해 보겠습니다. 해당 권리는 1
끝에서 두 번째와 세 번째 자리에 있는 비트에 의해 지정되며 , 이는 숫자를 나타냅니다 00110
(= 6
10번째 시스템).
const check = ACCESS_GOODS_VIEW | ACCESS_GOODS_EDIT; // 6, 00110
alert( admin & check ); // не 0, значит есть доступ к просмотру ИЛИ изменению
비트 마스크는check
원하는 위치에 있는 단위를 확인하고 선택하는 데 사용되는 이진 값의 조합입니다( 위의 예에서).
마스크는 매우 편안할 수 있다.
특히, 이는 여러 “플래그”를 하나의 매개변수로 전달하는 함수에서 사용됩니다. 즉, 1비트 값.
마스크로 함수를 호출하는 예:
// найти пользователей с правами на изменение товаров или администраторов
findUsers(ACCESS_GOODS_EDIT | ACCESS_ADMIN);
꽤 짧고 우아한 내용이지만, 동시에 마스크 사용에는 몇 가지 제한이 따릅니다. 특히, JavaScript의 비트 연산자는 32비트 숫자에서만 작동합니다. 즉, 예를 들어 33개의 액세스를 숫자로 묶을 수 없습니다. 그리고 이진수 체계를 사용하는 것은, 어떻게 보든, 십진수 체계나 일반적인 논리값을 사용하는 것보다 편리하지 않습니다 true/false
.
따라서 마스크의 주요 적용 분야는 빠른 계산, 메모리 절약, JavaScript(3D 그래픽)에서 그리는 것과 관련된 저수준 작업, 일부 OS 기능과의 통합(서버 측 JavaScript의 경우), 그리고 비트 마스크가 필요한 기능이 이미 존재하는 기타 상황입니다.
반올림
비트 연산은 소수 부분을 버리므로 반올림에 사용할 수 있습니다. 숫자의 값을 변경하지 않는 모든 연산을 수행하면 됩니다.
예를 들어, 이중 NOT( ~
)은 다음과 같습니다.
alert( ~~12.345 ); // 12
0을 사용한 배타적 OR( ^
)도 작동합니다.
alert( 12.345 ^ 0 ); // 12
후자는 완벽하게 읽히므로 더욱 편리합니다.
alert(12.3 * 14.5 ^ 0); // (=178) "12.3 умножить на 14.5 и округлить"
비트 연산자는 다른 산술 연산자보다 우선순위가 낮습니다.
alert( 1.1 + 1.2 ^ 0 ); // 2, сложение выполнится раньше округления
-1을 확인하세요
32비트 숫자 의 내부 형식은 부호를 변경하려면 모든 비트를 반대 비트로 바꿔서(“역전”) 추가해야 하도록 설계되었습니다 1
.
비트 반전은 비트 단위 NOT( ~
)입니다. 즉, 이러한 숫자 표현 형식을 사용하면 -n = ~n + 1
. 또는, 하나를 옮기는 경우: ~n = -(n+1)
.
마지막 등식에서 볼 수 있듯이, ~n == 0
오직 n == -1
. 따라서 쉽게 동등성을 확인할 수 있습니다 n == -1
.
let n = 5;
if (~n) { // сработает, т.к. ~n = -(5+1) = -6
alert( "n не -1" ); // выведет!
}
let n = -1;
if (~n) { // не сработает, т.к. ~n = -(-1+1) = 0
alert( "...ничего не выведет..." );
}
-1
예를 들어, 문자열에서 문자를 검색할 때 ‘확인’ 기능이 유용합니다. 호출은 str.indexOf("подстрока")
문자열의 위치를 반환하고 str
, -1
찾을 수 없으면 반환합니다.
let str = "Проверка";
if (~str.indexOf("верка")) { // Сочетание "if (~...indexOf)" читается как "если найдено"
alert( 'найдено!' );
}
2의 거듭제곱으로 곱하기와 나누기
연산자 a << b
는 비트를 이동하여 본질적으로 를 거듭 제곱 a
으로 곱합니다 .2
b
예를 들어:
alert( 1 << 2 ); // 1*(2*2) = 4
alert( 1 << 3 ); // 1*(2*2*2) = 8
alert( 3 << 3 ); // 3*(2*2*2) = 24
이러한 곱셈의 최대 상한은 일반적인 연산자보다 작다는 점에 유의해야 합니다. 비트 연산자는 32비트 정수를 처리하는 반면, 일반 연산자는 64비트 숫자를 처리하기 때문입니다.
이동 연산자는 정수 를 로 a >> b
나누는 역연산을 수행합니다 .a
2b
alert( 8 >> 2 ); // 2 = 8/4, убрали 2 нуля в двоичном представлении
alert( 11 >> 2 ); // 2, целочисленное деление (менее значимые биты просто отброшены)
총
- 이진 비트 연산자:
& | ^ << >> >>>
. - 단항 비트 연산자는 하나뿐입니다:
~
.
일반적으로 숫자의 비트 표현은 다음과 같은 용도로 사용됩니다.
- 숫자의 반올림:
(12.34^0) = 12
. - 평등성 검사
-1
:if (~n) { n не -1 }
. - 여러 비트 값(“플래그”)을 단일 값으로 묶습니다. 이렇게 하면 메모리가 절약되고 하나의 문장으로 여러 플래그의 조합을 확인할 수 있습니다
&
. - 비트 마스크가 필요한 상황도 있습니다.
작업
비트 연산자와 값
중요도: 5
아래 예시의 비트 연산이 숫자를 변경하지 않는 이유는 무엇입니까? 그들은 안에서 무엇을 하고 있을까?
alert( 123 ^ 0 ); // 123
alert( 0 ^ 123 ); // 123
alert( ~~123 ); // 123
해결책
숫자가 정수인지 확인
중요도: 3
정수 이면 값을 반환하고 , 그렇지 않으면 isInteger(num)
값을 반환하는 함수를 작성하세요 .true
num
false
예를 들어:
alert( isInteger(1) ); // true
alert( isInteger(1.5) ); // false
alert( isInteger(-0.5) ); // false
해결책
^, |, & 연산은 대칭입니까?
중요도: 5
a
다음 등식이 성립하는 것은 사실인가 b
?
(a ^ b) == (b ^ a)
(a & b) == (b & a)
(a | b) == (b | a)
즉, 장소를 바꾸어도 결과는 항상 같을까?해결책
왜 결과가 다른가요?
중요도: 5
두 번째 결과가 왜 alert
그렇게 이상한가요?
alert( 123456789 ^ 0 ); // 123456789
alert( 12345678912345 ^ 0 ); // 1942903641
해결책