파트 1 - 자바스크립트 기본 - 8) 기본 연산자와 수학

Lee·2021년 9월 26일
0
post-thumbnail


학창시절 수학에 맥을 못춰서 지금도 수학이라면 별로 달갑지 않다. 나한테 계산을 시키는 것도 아니고 단순히 연산자 설명이 있지만 거부감이 드는 파트였다.
거부감과는 별개로 내용은 물론 유익하며 이해하기 쉬우면서도 상세하게 설명 되어 있고 필수로 알아야 할 내용이다!!
매번 이런 시시콜콜한 코멘트를 남기는 이유는 나중에 다시 읽을 내가 재밌게 읽을 거라고 생각하기 때문이다.

8) 기본 연산자와 수학 : https://ko.javascript.info/operators

우선 간단한 용어정리가 필요하다.

  1. 피연산자(또는 인수) : 연산의 대상이 되는 값을 의미한다.
    ex) 1 + 5 에서의 피연산자는 덧셈 연산의 대상이 되는 1과 5 두 숫자다.

  2. 단항연산자(unary) : 피연산자가 1개 오는 연산자.

  3. 이항연산자(binary) : 피연산자가 2개 오는 연산자.

단항연산자로는 -, + 가 있는데 이 마이너스, 플러스 연산자는 이항 연산자로 사용하면 아시다시피 피연산자들에 대한 뺄셈, 덧셈 연산을 수행한다.

단항연산자로 쓰일 경우에는? 전혀 다른 기능을 수행한다!
단항연산자로서의 -는 피연산자의 부호를 반대 부호로 뒤집는 기능을 한다!

let x = 1;

x = -x;
alert( x ); // -1, 단항 마이너스 연산자는 부호를 뒤집습니다.

위의 예시 코드처럼 숫자 1에 단항연산자 -를 붙이면 -1이 되는 것이다. (너무 당연해 보이지만 그렇다.)
반대로 아래 코드를 수행하면 -1 에서 부호가 뒤집힌 1이 반환된다.

let x = -1;
x = -x;
alert( x ); // 1

단항 마이너스 연산자는 뺄셈 기호인 이상 마이너스 연산자와 모양은 같지만 수행하는 연산은 다르다.


기본적인 수학 연산자들

우리가 알고 있는 수학 연산자들이 나온다.
덧셈 : +
뺄셈 : -
곱셈 : *
나눗셈 : /
나머지 : %
거듭제곱 : **

다른 연산들은 많이 보던 것들인데 나머지와 거듭제곱은 주목할 필요가 있어 보인다. (일상에서 자주 쓰지 않기 때문에)

1) 나머지 연산은 나눗셈을 하고 나온 몫외에 나머지 값을 '정수'로 반환한다.

alert( 5 % 2 ); // 5를 2로 나눈 후의 나머지인 1을 출력
alert( 8 % 3 ); // 8을 3으로 나눈 후의 나머지인 2를 출력

2) 거듭제곱 연산은 a 거듭제곱 연산자 b 를(velog에서 곱셈 연산자를 두번 연달아 쓰는 기호가 글씨를 진하게 하는 기호라서 작성할 수 없다.) 수행할 경우 a를 b번 곱한 값(= a를 b번 제곱한 값)을 반환한다.
또 이 거듭제곱은 정수로만 제한되지 않는다. 1/2 제곱 같은 것도 가능하다!

alert( 2 ** 2 ); // 4  (2 * 2)
alert( 2 ** 3 ); // 8  (2 * 2 * 2)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2)

alert( 4 ** (1/2) ); // 2 (1/2 거듭제곱은 제곱근)
alert( 8 ** (1/3) ); // 2 (1/3 거듭제곱은 세제곱근)

3) 이항연산자 + 의 문자열 연결

이항연산자 + 는 단순히 숫자의 덧셈만 수행하는 것이 아닌 문자열끼리의 연결 기능을 하기도 한다.

let s = "my" + "string";
alert(s); // mystring

그래서 주의할 사항이 있다!
이항연산자 +의 피연산자 중 하나라도 문자열이면 다른 피연산자 또한 문자열로 변환 된다!

alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"

alert(2 + 2 + '1' ); // '221'이 아니라 '41'이 출력됩니다.
//왼쪽부터 오른쪽으로 연산이 진행 되어 왼쪽의 숫자 2, 2 에 대해서는 
//덧셈 연산이 일어난 후 문자열 '1'에 대한 연산이 일어났기 때문.

이항연산자 - 와 이항연산자 / 는 연산 중 문자열이 섞이면 해당 문자열을 숫자형으로 형 변환 후 연산을 진행하는 것과는 완전히 다르다.

alert( 6 - '2' ); // 4, '2'를 숫자로 바꾼 후 연산이 진행됩니다.
alert( '6' / '2' ); // 3, 두 피연산자가 숫자로 바뀐 후 연산이 진행됩니다.

4) 단항 연산자 +와 숫자형으로의 변환

이 단항 연산자 + 는 업무 중 실제로 사용한 경험이 있다. TypeScript를 사용 도중 특정 상황에서 && 기호를 사용하려 하면 수학 연산으로 받아들이는지 왼쪽 혹은 오른쪽에 숫자를 넣어야 한다는 경고문이 출력 되는 것이다.
그럴 때 검색을 통해 얻은 답이 단항연산자 +를 해당 값에 붙여주라는 것이였다.

단항 연산자 + 는 숫자가 아닌 값을 숫자형으로 변환해주는 기능을 한다.

// 숫자에는 아무런 영향을 미치지 않습니다.
let x = 1;
alert( +x ); // 1

let y = -2;
alert( +y ); // -2

// 숫자형이 아닌 피연산자는 숫자형으로 변화합니다.
// 예시 외에도 궁금한 건 바로 콘솔창에 입력해보면 답을 볼 수 있다.
alert( +true ); // 1
alert( +"" );   // 0, boolean 형변환과는 다르게 스페이스 값을 넣어도 0으로 나온다.
alert( +"3" ); // 3
alert( +undefined ); // NaN
alert( +null ); // 0

즉, 단항 연산자 + 는 Number(값) 와 같은 역할을 해주는 것인데 더 짧은 수식으로 수행할 수 있게 해주는 것이다.
이항연산자와 조합하여 쓸 수도 있다.

let apples = "2";
let oranges = "3";

// 이항 덧셈 연산자가 적용되기 전에, 두 피연산자는 숫자형으로 변화합니다.
alert( +apples + +oranges ); // 5

// `Number(...)`를 사용해서 같은 동작을 하는 코드를 작성할 수 있지만, 더 기네요.
// alert( Number(apples) + Number(oranges) ); // 5

이항 연산자와 함께 썼을 경우 단항 연산자가 먼저 동작하여 문자열이 숫자로 형 변환 되는 이유는?

연산자 우선순위 때문이다!


연산자 우선순위

단항 연산자들을 같은 모양의 이항 연산자들 보다 우선순위가 높다.
이 우선순위를 무시하고 원하는 순서대로 쓰고 싶다면 괄호 '()' 를 이용하면 된다.
예를 들어 곱셈과 덧셈을 같이 쓸 경우 곱셈이 우선순위가 높아 곱셈 먼저 연산되지만 덧셈 부분을 괄호로 감싸주면 덧셈 먼저 수행 된다.

1 + 2 * 5 // 곱셈이 먼저 수행되기 때문에 11 이 나온다.

( 1 + 2 ) * 5 // 덧셈이 먼저 수행되기 때문에 15 가 나온다.

우리가 그냥 사용하는 = 도 할당 연산자다!

= 은 할당 연산자로 우선순위가 3위 정도로 낮다.
그래서 x = 1+2*5; 같은 수식을 적었을 때 = 뒤의 연산을 모두 마친 뒤 그 결과를 x에 할당하는 것이다.

대부분의 연산자들은 단순히 동작을 수행하는 게 아니라 동작을 수행한 후 값을 반환한다.

할당 연산자 = 역시 값을 할당하는 것 뿐만 아니라 값을 반환한다!
예를 들어 x = value;를 수행할 경우 x에 value를 할당하는 동작을 수행 하고, value를 반환하는 것이다!

전혀 몰랐다. 위 예시를 보고 답이야 맞혔지만 그냥 'a에 저장된 값을 꺼내와서 사용하나??' 정도로 생각했다.

또, 할당 연산자를 여러번 이어서 할당 연산자 체이닝 이라고 부르는 방식으로도 사용할 수 있는데

let a, b, c;

a = b = c = 2 + 2;

alert( a ); // 4
alert( b ); // 4
alert( c ); // 4

보시다시피 우선순위가 높은 우측의 연산이 먼저 수행 되고 그 뒤 좌측에 있는 변수들에 순서대로 연산된 값이 할당된다. 그냥 이런 게 있다는 거고... 가독성이 좋지는 않아서 아래 방식을 권유 한다고 적혀있다.

c = 2 + 2;
b = c;
a = c;

할당 연산자 파트에 뭐가 많다...


복합 할당 연산자

뭔가 복잡한 내용을 설명할 것 같은 제목과는 다르게 우리가 흔히 보던 (나는 특히 반복문에서 많이 봤다.)
+=, -= 기호가 바로 복합 할당 연산자다. (사용한적은 없지만 *=, /= 도 있다.)

복합 할당 연산자의 우선순위는 할당 연산자와 동일하여 대부분의 다른 연산자가 실행된 뒤에 실행된다.

let n = 2;
n *= 2 + 5;
// n 은 14를 반환한다! 우선순위가 낮아서 2+5가 먼저 실행 되고 복합 할당 연산자를 실행했기 때문에 2 * 7이 된다.

증가·감소 연산자

증가 감소 연산자 또한 우리가 자주 보던 ++, -- 연산자다!

사용법은 ++변수, --변수 이렇게 쓰거나 변수++, 변수-- 이렇게 쓴다. 변수에만 쓰일 수 있지 ++5 이런식으로 숫자에 쓸 수는 없다.
이 연산자는 해당 변수의 값을 1만큼 증가 시키거나 1만큼 감소 시킨다.

위처럼 피연산자(변수)의 앞에 붙이는 것(++변수) 을 '전위형 (postfix form)', 피연산자의 뒤에 붙이는 것(변수++)'후위형 (prefix form)' 이라고 한다.

그렇다면 전위형과 후위형의 차이점은 무엇일까?
차이점은 반환값을 사용하려 할 때 보인다. (증가/감소 연산자도 연산자이기 때문에 당연히 값을 반환한다.)
아래 코드를 살펴보자.

let num = 1;
++num;
num++;
alert(3);
// 위 두 연산 다 똑같이 num을 1씩 늘리는 연산을 수행했다.
//---------------------------------------------------

let num = 1;
alert(++num); // 2 를 반환

//반면에 

let num = 1;
alert(num++); // 1을 반환

후위형 증감연산자는 연산을 수행하여 변화된 값이 아닌 기존 값을 반환한다. 이걸 모르고 증감연산자를 사용하면 원하는 값이 나오질 않으니 환장할 노릇이다.
코딩을 처음 배울 때 후위형 증감연산자를 사용하여 원하는 값을 얻지 못한 경험이 있다.

즉, 증감 연산자로 연산된 값을 바로 사용하고 싶으면 연산된 값이 반환되는 전위형 증감 연산자를 사용해야 한다!
반대로 연산은 수행하되 기존 값을 사용하고 싶다면 후위형 증감 연산자를 사용하면 된다.

증감연산자의 또다를 특징으로는 우선순위가 대부분의 연산자들 보다 높다는 것이다.

let counter = 1;
alert( 2 * ++counter ); // 4

let counter = 1;
alert( 2 * counter++ ); // 2 , 후위연산자 사용하여 기존 값이 반환 되기 때문에.

위와 같이 다른 연산과 사용할 수 있지만... 역시나 가독성 문제가 있다. 아래와 같이 사용하길 권장 하고 있다.

let counter = 1;
alert( 2 * counter );
counter++;
//여기서 counter++를 출력하면 기존값인 1이 나오겠지만 counter 를 출력하면 정상적으로 증가 연산을 마친 2가 출력된다.

비트 연산자

언제 봐도 헷갈리고 쉽게 잊어버리는 비트 연산자다.
'비트 연산자(bitwise operator)는 인수를 32비트 정수로 변환하여 이진 연산을 수행합니다.' 라고 한다.
비트 연산자는 자바스크립트 뿐만 아니라 다른 언어에서도 볼 수 있다.

위 캡처에 등장한 MDN의 비트 연산자 문서 링크 : https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators


쉼표 연산자 (comma operator)

쉼표 연산자는 여러 연산을 한줄에서 평가하기 위해 사용된다. ex) alert(1+2, 3+4) 이렇게 되면 두 연산을 한 줄에서 평가할 수 있는데 특이점은 두 연산 모두 반환하는 것이 아니라 뒤에 있는 마지막 연산만 반환한다! (따라서 예시로 든 코드는 7을 반환)

또, 우선순위가 할당 연산자 보다 낮기 때문에 아래와 같이 할당 연산자와 함께 쓰면 a=1+2 가 먼저 수행 되고 3+4 가 따로 진행된다.

1+2 와 3+4를 같이 평가하고 그 결과를 a에 할당 하고 싶은 거였다면 a = (1+2, 3+4); 이렇게 괄호를 써줬어야 한다.

대체 이 마지막 값만 덜렁 가져오는 연산을 어디에서 쓸까?
답은 아래 캡쳐에 있다.


이번 챕터는 정리 하는 데 시간이 꽤 걸렸다.
과연 이미 정리 되어 있는 문서를 이렇게 내가 다시 하나하나 정리해가며 공부하는 것이 효율적인 공부법인지 모르겠다. 그냥 읽고 넘어가는 식으로 공부했다면 아까 이미 끝났을 챕터다.

문제풀기에서 조금 틀렸다.
7/0 의 답이 뭘까? Infinity 라는 숫자형의 반환 값도 있다는 걸 있지 말자.
\t \n 은 공백으로 인식 되어 숫자로 변환시 0 이 된다는 것도.
NaN과 숫자 연산이 일어나면 그냥 NaN으로 반환 된다는 것도.

이미 정리가 잘 되어 있는 문서이기 때문에 오답노트 처럼 몰랐다가 알게 된 내용, 정말 중요해 보이는 내용만 골라서 정리하는 게 나을 것 같다.

만약 전부 다 모르고 새로 알게 된 내용이라면?
어쩔 수 없다...^^

profile
하고 싶은 게 너무 많습니다.

0개의 댓글

관련 채용 정보