[JS] tilde(~)과 double tilde(~~)연산자

Kyle·2021년 2월 16일
25

javascript

목록 보기
13/18

leetcode를 풀면서 ~~연산자를 사용한 풀이를 보고 되게 유용한 연산자라고 생각돼 간략하게 정리해보려한다. double tilde연산자를 이해하기 위해 tilde연산자를 알아보고나서 double tilde연산자에 대해서 알아볼 계획이다.

tilde(~) 연산자

tilde 연산자는 비트연산자로 NOT의 기능을 한다고 생각하면 된다.
아래와 같이 2진수일 때 0과 1만 뒤바꾸면 된다.

const a = 5;     // 0000000000000101
console.log(~a); // 1111111111111010
// expected output: -6

const b = -3;    // 1111111111111101
console.log(~b); // 0000000000000010
// expected output: 2

하지만 저것을 콘솔에 실행시켜 보면 expected output마냥 -6,2만 나오게 된다. 이를 이진수로 직접 눈으로 확인 하는 법은 없을까?

toString를 이용해 간단하게 2진수로 변환하기

toString메소드를 활용하면 10진수를 간단하게 2진수로 변환할 수 있다.

const a = 8
console.log(a.toString(2)) // 1000

하지만 이렇게 했을 때 한가지 문제점이 발생한다. 아래의 코드가 어떻게 실행되는지 예상해보자.

const b = -8
console.log(b.toString(2))

1111111111111111111111111111000 이렇게 1000의 보수가 나와야 할것만 같지만 -1000으로 나와버린다. 이렇게되면 not연산자를 제대로 확인할 수 없다.

이를 해결하기 위해 비트 시프트 연산자 중 >>>를 활용할 수 있다.

>>> 연산자

>>> 연산자는 >> 연산자와 비슷하지만 둘의 차이는 값이 음수 일 때 차이가 있다.

mdn의 예시로 확인해보자.

  • >> 연산자 예시
-9 (10진수): 11111111111111111111111111110111 (2진수)
                   --------------------------------
-9 >> 2 (10진수): 11111111111111111111111111111101 (2진수) = -3 (10진수)
  • >>> 연산자 예시
-9 (10진수): 11111111111111111111111111110111 (2진수)
                    --------------------------------
-9 >>> 2 (10진수): 00111111111111111111111111111101 (2진수) = 1073741821 (10진수)

차이는 >>연산자는 1이라면 1로 채우면서 왼쪽으로 밀지만 >>>연산자는 0으로 채우면서 민다.

이 특징을 활용하여 음수 역시 2진수로 변환시킬 수 있다.

이제 다시 위로 돌아가자.

아래 코드와 같이 b>>>0를 활용해서 음수역시 2진수로 볼 수 있다.

const b = -8
console.log((b>>>0).toString(2)) 
//11111111111111111111111111111000

이제 tilde(~)연산자가 어떻게 되는지 확인했다.


이글의 목적이었던 double tilde(~~)연산자에 대해서 알아보자. 왜 이렇게 뻘소리가 길어졌는지...??? 본론은 간단하다!

double tilde(~~)

사실 별거 없다. tilde를 2번 반복해주는 것이다.

let k = 8 이라고 했을 때 ~k는 무엇일까? -9 이다. (why? ~은 보수가 아닌 not이기 때문) 그럼 ~~k는?? 그렇다 원래대로 8이다.

double tilde연산자가 어떻게 유용하게 사용되는지 알아보자.

1. Math.floor() 대신 사용될 수 있다.

숫자에 ~연산을 하게되면서 소수점들은 버려지게된다. 즉, ~~를 활용하면 Math.floor() 처럼 활용할 수 있다.

Math.floor() 대신에 활용하는데 장점과 단점이 있다.

장점

속도 측면에서 ~~가 빠르다고 한다. The Mysterious Double Tilde (~~) Operation 이 블로그에 보면 크롬, Safari,iPhone XS 각각Math.floor, ~~, parseInt 의 속도를 비교한 결과가 있다.

결과는 ~~ , Math.floor, parseInt 순으로 ~~가 가장 빠른 퍼포먼스를 보여줬다.

단점

코드에 ~~가 덕지덕지 있다고 상상해보자. 이해가 쉽지 않을 것이다. 복잡한 코드 또는 협업하는 과정에서는 가독성이 좋지 않기 때문에 사용하지 않는편이 좋을 것 같다.

2. undefined 또는 null을 0으로 변환할 때 사용될 수 있다.

위의 경우가 언제쓰일까 싶지만 undefined+3 => NaN 이런 상황이 자주 있었을 것이다.

예시 하나만 작성해 보자.
배열[1,1,1,2,2,3,3,3,3]을 각 숫자가 몇개인지 객체에 저장해보자.

const arr = [1,1,1,2,2,3,3,3,3]
const obj1 = {}

arr.forEach(v=>{
  if(obj1[v]) obj1[v]+=1
  else obj1[v]=1
})
//obj1 {1: 3, 2: 2, 3: 4}

위와같이 obj에 key값이 있는지 확인해주는 작업이 필요하다. 그렇지 않으면 NaN이 나올 것이다.

그럼 ~~를 활용해 다시 코드를 작성해보자.

const obj2 = {}
arr.forEach(v=>obj2[v]= ~~obj2[v]+1)
//obj2 {1: 3, 2: 2, 3: 4}

undefined가 나올 수 있는 상황을 ~~연산자를 이용해서 간단하게 해결할 수 있다. 알고리즘 답안을 보면서 배운 연산자인 만큼 알고리즘에서 유용하게 사용할 수 있을 것 같다.

마무리

이외에도 ~~연산자는 다양하게 활용될 수 있다고 생각된다. ~~연산자를 알아보면서 비트쉬프트 연산자도 공부하게 됐고, ~연산자에 대해서도 조금은 자세하게 알아볼 수 있어서 좋았다.

profile
Kyle 발전기

3개의 댓글

comment-user-thumbnail
2022년 10월 4일

잘 배우고 갑니다. 감사합니다

답글 달기
comment-user-thumbnail
2023년 5월 28일

자세한 설명 감사합니다. 많이 배웠습니다.

답글 달기
comment-user-thumbnail
2023년 12월 26일

I appreciate the thorough explanation; it was very informative, and I gained a lot of knowledge from it. Toca Life World mod APK

답글 달기