부울에서 비트 단위 연산은 어떻게 작동합니까?


26

나는 Edabit 에서이 도전에 부딪 쳤고이 비트 연산 솔루션을 해결할 수 없었습니다.

notNotNot = (a,b) => !!(a%2 >> b)

도전 과제 :

//Something which is not true is false, but something which is not not true is true! 
//Create a function where given n number of "not", evaluate whether it's true or false.

//Examples:
notNotNot(1, true)  false
// Not true

notNotNot(2, false)  false
// Not not false

notNotNot(6, true)  true
// Not not not not not not true

나는 그 연산자에 대해 조사했다 :

가장 왼쪽 비트를 왼쪽에서 밀어 넣어 오른쪽으로 이동하고 가장 오른쪽 비트는 떨어지게합니다.

내가 이해 한다고 생각하지만 (예 : 5 >> 1으로 0101 >> 1평가되는 것과 동일 0010) 부울과 어떻게 작동하는지 볼 수 없습니까? 나는 알고 true로 평가 1하고 false을을 0.


3
부울은 숫자로 변환되고 시프트가 발생하므로 true= 1(10 진수) = 01(2 진수) 1 씩 왼쪽으로 시프트하면 102 진수 또는 210 진수 가 생성 됩니다.
VLAZ

실제로이 솔루션은 올바르지 않습니다. 위에서 언급 한 경우에는 효과가 있지만 다음 사항을 고려하십시오 notNotNot(2, true). 반환 할 false것이지만 사실 !!true은 아닙니다 true.
FZ

@FZs 맞습니다. 이 함수는를 false해결하기 위해 홀수 개의 노트 만 고려합니다 true.
VLAZ

2
내가 notNotNot = (a,b) => !!((a%2)^b)대신 말하고 싶습니다
FZ

왜 안돼 (a, b) => !!((a + b) % 2)?
Jonas Wilms

답변:


16

당신이 준 기능은 도전을 만족시키지 않습니다. 올바른 이동은 요청 된 작업을 수행하지 않습니다. 예를 들어, notNotNot(6,true)IS가 false아닌 true함수를 넣을 때.

귀하의 질문은 부울에서의 비트 연산에 관한 것입니다. 연산자 는 정수를 좋아 >>하고 <<작업 하기 때문에 Javascript는 먼저 부울 값을 정수로 변환합니다. 따라서 true1 false이되고 0이됩니다. 이것을보기 위해 0 씩 이동할 수 있습니다 :

console.log("true is",true >> 0)
console.log("false is", false >> 0)
따라서 부울의 비트 연산은 실제로 0 또는 1의 비트 연산입니다.

사용 !!은 모든 것을 부울로 변환하는 편리한 방법입니다. false (예 : 0 null, undefined또는 "")와 동등한 것으로 간주되는 모든 것을 가져 옵니다 false. 마찬가지로 14, "hello", [4], {a : 1}와 같이 진실되고 되돌려주는 모든 것 true. !!첫 번째 느낌표는 항상 true또는 false인 표현식의 'not'을 제공하고 두 번째 느낌표는 그 반대 ( false또는 true) 를 제공하기 때문에 작동합니다 .

도전으로 돌아가서, 비 연산자 'a'를 적용하고 'b'값과 비교하려고합니다. 따라서 이와 같은 것이 효과가 있습니다.

function notNotNot(a, b) { return !!(a%2 - b); }
console.log("notNotNot(1, true)",notNotNot(1, true));
console.log("notNotNot(2, false)",notNotNot(2, false));
console.log("notNotNot(6, true)",notNotNot(6, true));


9
나는 "도전"이 당신이 루프없이 쉽게 이것을 할 수 있다는 것을 깨닫기를 원한다고 생각합니다.
BlueRaja-Danny Pflughoeft

2
@ BlueRaja-DannyPflughoeft는 실제로. 루프없이 그것을하는 가장 간단한 방법은 if (a % 2 === 1) return !b else return b있지만 다른 답변에서 볼 수 있듯이 분기 또는 루프없이 할 수있는 방법이 있습니다.
VLAZ

예, 그러나 문제는 도전에 관한 것이 아니라 비트 연산자와 부울 값에 대한 것입니다. 그러나 나는 루프가 아닌 방식으로 대답을 업데이트했습니다.
항상 학습

14

비트 연산자는 항상 피연산자를 정수로 변환합니다. 따라서 한 위치만큼 비트 시프트를 수행하는 4 >> true것과 동일합니다.4 >> 1

(decimal) 4 = (binary) 100

(binary) 100 >> 1 = (binary) 010

(binary) 010 = (decimal) 2

console.log(4 >> true);

그래서, 사용 true또는 것은 false사용에 단지 로터리 방법 10.

notNotNot기능은 전체적으로 매우 간단한 작업을 수행합니다.

  1. a%2첫 번째 숫자 0를 짝수 또는 1홀수 로 변환합니다 .
  2. >> b0위치 중 하나를 오른쪽으로 이동false 또는 1위치 합니다 true.
    • a 홀수 (1) b이다 false=1
      • 오른쪽으로 0의 시프트가 있으므로 숫자는 동일하게 유지됩니다.
    • a 홀수 (1) b이다 true=0
      • 유일하게 설정된 비트 1 오른쪽으로 이동하여 버립니다.
    • a 짝수 (0)이고 bfalse=0
      • 오른쪽으로 0의 시프트가 있으므로 숫자는 동일하게 유지됩니다.
    • a 짝수 (0)이고 btrue=0
      • 기본 번호는 0비트가 설정되어 있지 않으므로 금액을 오른쪽으로 이동해도 변경되지 않습니다.
  3. !!() 결과를 부울로 변환합니다.

그렇게 말 때문에, 여기에 해결책은, 잘못 notNotNot(2, true)생성 할 것이다 false- a도하고 b있다 true. 기대는 그것이 true이후 생산 될 것이라는 것입니다!!true = true . 짝수와에 동일한 문제가 true있습니다.

오른쪽 시프트 대신 비트 XOR을 사용하여 쉽게 수정할 수 있습니다.

  • a홀수 (1)이다 b이다 false=1
    • 둘 다 일치하므로 0
  • a홀수 (1)이다 b이다 true=0
    • 일치하지 않기 때문에 1
  • a심지어 (0)이고, bfalse=0
    • 둘 다 일치하므로 0
  • a심지어 (0)이고, btrue=1
    • 일치하지 않기 때문에 1

notNotNot = (a,b) => !!(a%2 ^ b);

console.log("!!true = ", notNotNot(2, true))
console.log("!!!true =", notNotNot(3, true))
console.log("!!false = ", notNotNot(2, false))
console.log("!!!false = ", notNotNot(3, false))

//bonus
console.log("true = ", notNotNot(0, true))
console.log("false = ", notNotNot(0, false))

완전한 비트 단위 연산을 원할 경우 완전성을 위해 다음을 수행하십시오.

모듈로 연산 %2을 비트 단위로 변경 &1하고 가장 낮은 비트를 얻을 수 있습니다 . 짝수의 0경우 컴퓨팅을 시작한 이후로

xxx0
&
0001

이것은 0입니다. 홀수에 대해서도 동일하지만 결과는 1입니다.

xxx1
&
0001

결과 지금 a&1과는 a%2동일하다. 또한 비트 단위 연산 은 숫자를 32 비트 부호있는 정수로 변환 하지만 패리티 가 유지 되므로 중요하지 않습니다 .


4

첫째, (a,b) => !!(a%2 >> b)예제의 결과와 일치하지 않습니다. 사용중인 작업을 정확하게 분석합니다 notNotNot(6, true) ➞ true.

  • 주먹 a%2, 단순히 a2를 나누고 나머지를 반환하십시오. 따라서 짝수의 경우 0, 홀수의 경우 1이됩니다.a = 6 a%2 = 0이 경우
  • 그런 다음에 평가 0 >> b한대로 1의 숫자를 오른쪽에서 true옮깁니다 1. 그래서 우리는 얻는다 0 >> 1 = 0.
  • 마지막 !!(0)으로 간단하고 !0 = true다음 과 같이 분류 할 수 있습니다 !true = false.

그래서 우리는 긴만큼 이것에 대해 생각하는 경우 b입니다 true, 우리는 항상 돌아 얻을 것이다 false. 하자 우리가 = 5, b는 = true로 평가가 있다고 5%2 = 1, 1 >> 1 = 0. mod ( %2) 때문에 1 또는 0 만 (1 자리 만) 가질 수 있으며 true는 항상 1에서 벗어납니다.

이 문제를 보는 간단한 방법은 isEvenOrNot함수 와 같습니다 . 따라서 a우리가 확인하고있는 숫자는 b짝수인지 (true) 짝수인지 (false) 확인하는 부울입니다. 이것은 매 초마다 작동합니다.not 추가 합니다.

따라서 비트 단위를 사용하는 솔루션은 다음과 같습니다 (a,b) => !!(a&1 ^ b). 나는 그것이 왜 작동하는지 재미있게 보내 줄 것입니다! :)

시프트가 부울과 어떻게 작동하는지 설명하는 데 조금 더 설명합니다. 그래서 true당신이 말한대로 한 것과 거짓은 0 그래서 같은 예에서와 같이 될 것 0101 >> true과 동일합니다 0101 >> 1.

이게 도움이 되길 바란다.

나는 비트에 대한 참조로 다음을 사용 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators


1
(a%2)  //ignore all but the least significant bit (LSB)
(a%2 >> b )  //if TRUE,  shifts right, resolves to 0
               //if FALSE, no shift,     resolves to LSB

// 0 and LSB are both integers so convert to boolean by using logical/boolean NOT
!(a%2 >> b ) //resolves to the boolean which it is NOT
!!(a%2 >> b ) //resolves to the boolean which it is NOT NOT

NB 부울의 경우 짝수의 NOT은 원래 부울의 결과이고 홀수의 NOT은 반대 부울의 결과입니다.

숫자의 LSB는 숫자가 홀수인지 짝수인지를 나타냅니다. (0 짝수, 1 홀수)


1

당신의 임무는 다음과 같습니다.

/* Create a function where given n number of "not",
   evaluate whether it's true or false.*/

나는 왜 당신이 notnotnot나를 위해 함수를 작성하는지 모르겠습니다 .

작업에 따라 그 기능을 만들었습니다 not 많은 "nots"를 받아들이고 평가 을 습니다.

첫 번째 방법

function not(n) {
  return Boolean(n - n - 1);
}

XOr을 사용하는 두 번째 방법 (^)

function not(n) {
  return Boolean(bool ^ (bool - 1));
}

@VLAZ가 지적한 Mod (%)를 사용하는 세 번째 방법

function not(n) {
  return Boolean(n % 2);
}

비트 단위 And (&)를 사용하는 네 번째 방법

function not(n) {
  return Boolean(n & 1);
}

테스트

not(0)
//> false 
not(1)
//> true
not(2)
//> false
not(515)
//> true

1
비트 조작은 양에 신경 쓰지 않기 때문에 유용합니다. n짝수인지 홀수인지에 관계없이 두 개의 NOT이 취소되기 때문에 !!!!!b와 동일합니다 !b. 따라서 방금 가져 가면 루프가 필요하지 않습니다. NOT을 n%2얻고 "똑같이 유지하십시오". 우리는 숫자가 있기 때문에 비트 단위 연산 만 할 수 있습니다. 10
VLAZ

글쎄, 난 그것에 대해 생각하지 않았지만 당신은 우리가 0과 1 만 다루고있어, 감사합니다, 이것은 유용한 의견입니다 :)
SaymoinSam

0

분석 솔루션을 먼저 보자

notNotNot(oddNumber, true)   false
notNotNot(evenNumber, true)  true

notNotNot(oddNumber, false)   true
notNotNot(evenNumber, false)  false

이제 분석 (a,b) => !!(a%2 >> b)

a%2 == 0  even number
a%2 == 1  odd number

// For a%2 == 0

a%2 >> b  if b is true   0 >> 1  0   // Not working
a%2 >> b  if b is false  0 >> 0  0


// For a%2 == 1

a%2 >> b  if b is true   1 >> 1  0
a%2 >> b  if b is false  1 >> 0  1

이 작동하지 않습니다 그게 수단 notNotNot(6, true)입니다 true하지만 현재의 솔루션을 제공합니다 false.

우리는 당신 ^(XOR) 연산자가 그것을 올바르게 만들 수 있습니까?(a,b) => !!(a%2 ^ b)

이제 분석 (a,b) => !!(a%2 ^ b)

a%2 == 0  even number
a%2 == 1  odd number

// For a%2 == 0

a%2 ^ b  if b is true   0 ^ 1  1   // Now working
a%2 ^ b  if b is false  0 ^ 0  0


// For a%2 == 1

a%2 ^ b  if b is true   1 ^ 1  0
a%2 ^ b  if b is false  1 ^ 0  1

!(a%2 ^ b) use `!` to make int as boolean but solution result will reversed then
!!(a%2 ^ b) use `!` again to reversed it again and make it correct.

예:

notNotNot = (a,b) => !!(a%2 ^ b);

console.log("!!!!true = ", notNotNot(4, true))
console.log("!!!!false = ", notNotNot(4, false))
console.log("!!!true =", notNotNot(3, true))
console.log("!!!false = ", notNotNot(3, false))

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.