본문 바로가기
알고리즘/[PRO] 삼성 SW 역량 테스트 B형

B형에 필요한 최적화 코드 (2)

by 피로물든딸기 2021. 2. 15.
반응형

삼성 B형 전체 링크

 

참고

- B형에 필요한 최적화 코드 (1)

- B형에 필요한 최적화 코드 (2)

- 함수의 매개변수와 배열의 register 속도 비교

- 삼성 B형 디버깅 Tip

- 비주얼 스튜디오 output.txt 설정하기

- 삼성 SW 역량 시험 환경에서의 인라인 함수

- Visual Studio LNK1168: 쓰기용으로 열 수 없습니다 해결방법

 

B형에 필요한 최적화 코드 (1)은 필수 최적화이고 기억하기 쉽다.

++i 사용하기, register로 선언하기, 전역 변수는 복사해서 사용하기로 외울 필요도 없고,

마지막 점검 때, 코드만 조금 다듬으면 된다.

 

(2)에서는 많이 사용하지는 않지만, 간단한 것을 모아보았다.

 

4) if/else vs switch/case

5) 비트 연산 : 나누기 2 vs >> 1  /  나머지

6) 비트 연산 : 대소문자 변환

7) 루프 풀기 Loop Unrolling

 


4) if/else vs switch/case

 

switch case가 더 빠르다.

그러나 이분 탐색이 필요한 경우에는 if/else로 binary breakdown을 사용할 수 있다.

int main(void)
{
	int x = 5;

	if (x < 4) /* 0 ~ 3 */
	{
		if (x < 2) /* 0 ~ 1 */
		{
			...
		}
		else /* 2 ~ 3 */
		{
			...
		}
	}
	else /* 4 ~ 7 */
	{
		if (x < 6) /* 4 ~ 5 */
		{
			...
		}
		else /* 6 ~ 7 */
		{
			...
		}
	}

	return 0;
}

5) 비트 연산 : 나누기 2 vs >> 1  /  나머지

 

비트 연산 >> 1이 나누기 2보다 빠르다.

 

비슷하게 숫자 m의 2n의 나머지는 m & (2n - 1)으로 구할 수 있다.

(2의 거듭제곱에 - 1을 하면 비트가 1만 남기 때문이다.)

int main(void)
{
	int x = 25;

	printf("%d\n", x & (4 - 1));  /* 25를 4로 나누면 나머지는 1 */
	printf("%d\n", x & (8 - 1));  /* 25를 8로 나누면 나머지는 1 */
	printf("%d\n", x & (16 - 1)); /* 25를 16으로 나누면 나머지는 9 */
	printf("%d\n", x & (32 - 1)); /* 25를 32으로 나누면 나머지는 25 */

	return 0;
}

6) 비트 연산 : 대소문자 변환

 

소문자 a와 대문자 A의 차이는 32 = 0x20이다.

이것을 이용하면 소문자를 대문자로 변경, 대문자를 소문자로 간단히 변경 가능하다.

또한 ^ 연산을 이용해 소문자인 경우는 대문자로, 대문자인 경우엔 소문자로 변경도 가능하다.

#include <stdio.h>

int main(void)
{
	char ch1 = 'a';
	char ch2 = 'B';
	char ch3 = 'c';

	printf("%d 0x%x\n", 'a' - 'A', 'a' - 'A');
	printf("== 소문자 변경 ==\n");
	printf("%c\n", ch1 | 0x20); /* a */
	printf("%c\n", ch2 | 0x20); /* b */
	printf("%c\n", ch3 | 0x20); /* c */
	printf("== 대문자 변경 ==\n");
	printf("%c\n", ch1 & ~0x20); /* A */
	printf("%c\n", ch2 & ~0x20); /* B */
	printf("%c\n", ch3 & ~0x20); /* C */
	printf("== 대/소문자 토글 ==\n");
	printf("%c -> %c\n", ch1, ch1 ^ 0x20);  /* a -> A */
	printf("%c -> %c\n", ch2, ch2 ^ 0x20);  /* B -> b */
	printf("%c -> %c\n", ch3, ch3 ^ 0x20);  /* c -> C */
	printf("== 대/소문자 체크 ==\n");
	printf("%d\n", ch1 & 0x20); /* 32 : 소문자 */
	printf("%d\n", ch2 & 0x20); /* 0  : 대문자 */
	printf("%d\n", ch3 & 0x20); /* 32 : 소문자 */
	printf("=======\n");

	return 0;
}

0x20이 있는 경우는 소문자 이므로, & 0x20을 해서 값이 있다면 소문자로 판단할 수 있다.


7) 루프 풀기 Loop Unrolling

 

루프 풀기를 하면 반복을 위한 계산이 줄어들고, 파이프라인의 파괴도 적어진다.

int a[100];
for (int i = 0; i < 100; i++) a[i] = i + 1;

/* --------------------------------------------------- */

for (int i = 0; i < 100; i += 4)
{
	a[i] = i + 1;
	a[i + 1] = i + 2;
	a[i + 2] = i + 3;
	a[i + 3] = i + 4;
}
반응형

댓글