1047 : [기초 - 비트 시프트 연산] 정수 1개 입력받아 2배 곱해 출력하기
문제 설명 : https://codeup.kr/problem.php?id=1047
정수를 입력받아 2배 곱해 출력하는 문제다.
- 비트 연산자를 배운다.
- 비트 연산자 중 시프트 연산을 사용한다.
비트 연산자란 자료형을 근거로 해석된 정보가 아니라, 일정 길이의 메모리에 담긴 2진수 정보를 말 그대로 비트 단위로 계산하는 연산자다.
C언어 비트 연산자는 &(AND), |(OR), ^(XOR), ~(NOT), <<(Shift left), >>(Shift right)가 있다.
이중 ~(NOT)은 단항 연산자고 나머지는 모두 2항 연산자다. 비트 단위 상수를 기술할 때는 보통 16진수를 사용한다.
여기서는 비트 연사자 중 시프트 연산을 배우고 다른 비트 연산자가 나왔을 때 자세히 배운다.
아주 간단하게 *(곱하기 연산자)를 사용해도 되지만 여기서는 비트 연산자를 배우고 그중 시프트 연산을 사용하는 문제다.
시프트 연산자란 피연산자의 각 자리(2진수로 표현했을 때)를 오른쪽 또는 왼쪽으로 이동한다고 해서 시프트 연산자라고 이름 붙여졌다.
예를 들어 '8 << 2'는 왼쪽 피연산자인 10진수 8의 2진수를 왼쪽으로 2자리 이동한다. 이때, 자리이동으로 저장 범위를 벗어난 값들은 버려지고 빈자리는 0으로 채워진다. 이 과정을 단계별로 살펴본다.
1. 10진수 8은 2진수로 '00001000'이다.
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
2. '8 << 2'는 10진수 8의 2진수를 왼쪽으로 2자리 이동시킨다.
0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
3. 자리이동으로 인해 저장 범위를 벗어난 값은 버려지고, 빈자리는 0으로 채워진다.
버려짐 | 버려짐 | 0 | 0 | 1 | 0 | 0 | 0 | 0(채워짐) | 0(채워짐) |
4. '8 << 2'의 결과는 2진수로 '00100000'이 된다. (10진수로 32)
버려짐 | 버려짐 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
>>(Shift right)는 반대로 오른쪽으로 이동한다.
시프트 연산의 예
수식 | 자리이동 | 연산결과 | |
2진수 | 10진수 | ||
8 >> 0 | 없음 | 00000000 00000000 00000000 00001000 | 8 |
8 >> 1 | 오른쪽으로 한 번 | 00000000 00000000 00000000 00000100 | 4 |
8 >> 2 | 오른쪽으로 두 번 | 00000000 00000000 00000000 00000010 | 2 |
-8 >> 0 | 없음 | 11111111 11111111 11111111 11111000 | -8 |
-8 >> 1 | 오른쪽으로 한 번 | 11111111 11111111 11111111 11111100 | -4 |
-8 >> 2 | 오른쪽으로 두 번 | 11111111 11111111 11111111 11111110 | -2 |
8 << 0 | 없음 | 00000000 00000000 00000000 00001000 | 8 |
8 << 1 | 왼쪽으로 한 번 | 00000000 00000000 00000000 00010000 | 16 |
8 << 2 | 왼쪽으로 두 번 | 00000000 00000000 00000000 00100000 | 32 |
-8 << 0 | 없음 | 11111111 11111111 11111111 11111000 | -8 |
-8 << 1 | 왼쪽으로 한 번 | 11111111 11111111 11111111 11110000 | -16 |
-8 << 2 | 왼쪽으로 두 번 | 11111111 11111111 11111111 11100000 | -32 |
더보기에 있는 예를 본다면 쉽게 이해할 것이다.
x << n은 x * 2^n의 결과와 같다. x >> n은 x / 2^n의 결과와 같다.
2진수의 자리이동이 왜 2^n으로 곱하거나 나눈 결과가 같은지 이해가 안 된다면 10진수 자리이동을 해보면 쉽다.
예를 들어 10진수 153을 오른쪽으로 2자릴 이동하면 15300이 되는데 이 값은 153에 10^2를 곱한 결과와 같다.
그러므로 10진수에서도 10^n을 곱하거나 나눈 결과를 얻는다.
곱셈이나 나눗셈 연산자를 사용하면 같은 결과를 얻을 수 있는데 굳이 시프트 연산자를 쓰는 이유는 속도 때문이다.
'8 >> 2'의 결과는 '8 / 4'의 결과와 같다. 하지만 '8 / 4'를 연산하는데 걸리는 시간보다 '8 >> 2'를 연산하는데 걸리는 시간이 더 적게 걸린다. 다시 말하면 '시프트 연산자'를 사용하는 것이 나눗셈, 곱셈 연산자를 사용하는 것보다 더 빠르다.
그러나 프로그램의 실행 속도도 중요하지만 프로그램을 개발할 때 코드의 가독성도 중요하다. 시프트 연산자가 속도가 빠르긴 해도 곱셈이나 나눗셈 연산자보다는 가독성이 떨어진다. 시프트 연산자보다 곱셈, 나눗셈 연산자를 주로 사용하고, 보다 빠른 실행 속도가 요구되는 곳에만 시프트 연산자를 사용하는 것이 좋다.
#include <stdio.h>
int main()
{
long long int x;
scanf("%lld", &x);
printf("%lld", x<<1);
return 0;
}
1048 : [기초 -비트 시프트 연산] 한 번에 2의 거듭제곱 배로 출력하기
문제 설명 : https://codeup.kr/problem.php?id=1048
1047에서 배운 비트 연산자 중 시프트 연산을 이용하여 거듭제곱을 출력하는 문제다.
비트 시프트 연산의 설명은 1047에 자세히 되어 있다.
- x << n은 x * 2^n의 결과와 같다.
- x >> n은 x / 2^n의 결과와 같다.
#include <stdio.h>
int main()
{
int x, y;
scanf("%d %d", &x, &y);
printf("%d", x<<y); // x << 1 = x*2^1, x << 2 = x*2^2, x << y = x*2^y
return 0;
}
1049 : [기초 - 비교 연산] 두 정수 입력받아 비교하기 1
문제 설명 : https://codeup.kr/problem.php?id=1049
두 정수를 입력받아 두 수를 비교하는 문제다.
- 비교 연산자(관계 연산자)를 배운다.
비교 연산자란 두 피연산자의 값을 비교해 참(True, 1), 거짓(False, 0)의 결과를 내는 연산자다.
'참'을 %d로 출력하면 1이고 '거짓'을 출력하면 0이라는 사실을 알아야 한다.
C언어에서 '참'의 정확한 의미는 "0이 아닌 모든 값"이다.
비교 연산자(관계 연사자)에는 >, <, >=, <=, ==, != 6개가 있다. '!='는 연산자를 처음 배울 때 1024에서 소개만 했었다.
비교 연산자 | 분류 | 의미 | 연산결과 |
A > B | 비교연산 | A는 B보다 크다. | A 값이 크면, True 아니면 False |
A < B | A는 B보다 작다. | A 값이 작으면, True 아니면 False | |
A >= B | A는 B보다 크거나 같다.(B이상) | A 값이 크거나 같으면, True 아니면 False | |
A <= B | A는 B보다 작거나 같다.(B이하) | A 값이 작거나 같으면, True 아니면 False | |
A == B | 상등연산 | A는 B와 같다.(즉, 뺄셈 결과가 0) | 두 값이 같으면, True 아니면 False |
A != B | 부등연산 | A는 B와 같지 않다. | 두 값이 다르면, True 아니면 False |
#include <stdio.h>
int main()
{
int x, y;
scanf("%d %d", &x, &y);
printf("%d", x>y);
return 0;
}
1050 : [기초 - 비교 연산] 두 정수 입력받아 비교하기 2
문제 설명 : https://codeup.kr/problem.php?id=1050
두 정수를 입력받아 두 수를 비교하는 문제다.
1049와 같은 유형이다.
- 1049에서 배운 비교 연산자를 사용한다.
- '=' 단순 대입 연산자와는 전혀 다른 의미로 사용된다.
#include <stdio.h>
int main()
{
int x, y;
scanf("%d %d", &x, &y);
printf("%d", x==y);
return 0;
}
1051 : [기초 - 비교 연산] 두 정수 입력받아 비교하기 3
문제 설명 : https://codeup.kr/problem.php?id=1051
두 정수를 입력받아 두 수를 비교하는 문제다.
1049와 같은 유형이다.
- 1049에서 배운 비교 연산자를 사용한다.
#include <stdio.h>
int main()
{
int x, y;
scanf("%d %d", &x, &y);
printf("%d", x<=y);
return 0;
}
1052 : [기초 - 비교 연산] 두 정수 입력받아 비교하기 4
문제 설명 : https://codeup.kr/problem.php?id=1052
두 정수를 입력받아 두 수를 비교하는 문제다.
1049와 같은 유형이다.
- 1049에서 배운 비교 연산자를 사용한다.
#include <stdio.h>
int main()
{
int x, y;
scanf("%d %d", &x, &y);
printf("%d", x!=y);
return 0;
}
'CodeUp 기초 100제 > C' 카테고리의 다른 글
CodeUp[코드업] C언어 1063 ~ 1070 : [기초 - 삼항연산] ~ [기초 - 조건/선택 실행구조] (0) | 2019.12.09 |
---|---|
CodeUp[코드업] C언어 1053 ~ 1062 : [기초 - 논리 연산] ~ [기초 - 비트단위 논리 연산] (0) | 2019.12.09 |
CodeUp[코드업] C언어 1038 ~ 1046 : [기초 - 산술 연산] (0) | 2019.12.08 |
CodeUp[코드업] C언어 1028 ~ 1037 : [기초 - 데이터형] ~ [기초 - 출력 변환] (0) | 2019.12.07 |
CodeUp[코드업] C언어 1020 ~ 1027 : [기초 - 입출력] (0) | 2019.12.05 |
댓글