|  컴퓨터 구조

 

 

01. 컴퓨터의 큰 구조

- 컴퓨터는 크게 하드웨어소프트웨어로 나누어집니다. 

- 집에 있는 컴퓨터를 열어보면 그 안에 하드웨어를 볼 수 있는데,

   크게 1) CPU, 2) 메모리, 3) Storage, 4) Network, 5) IO 장치로 나누어져요.

- 소프트웨어에는 시스템 소프트웨어와 응용 소프트웨어가 있는데요,

  시스템 소프트웨어 운영체제(OS)장치 드라이버와 같이 사용자가 컴퓨터를 작동할 수 있게 하는 유틸리티를 말하며

  응용 소프트웨어(= Application software)오라클이나 게임과 같이 특정 문제나 업무를 처리하기 위한 목적으로 만들어진 소프트웨어를 말합니다.

 

[참고 : 양자 컴퓨터]


- 양자 컴퓨터는 양자의 기본 성질인 중첩, 얽힘 등을 사용해서 다수의 정보를 처리할 수 있는 새로운 컴퓨터를 말합니다.
- 오늘날의 트랜지스터(일종의 스위치)는 반도체 칩에서 원자의 크기로 나아가고 있다고 해요 (HIV바이러스보다 작은 크기)
- 큐비트 곧, 1과 0이 동시에 존재하는 '중첩'으로 양자 병렬처리가 가능해서 속도가 엄청나게 빨라지게 되었다고 해요.
- 양자 컴퓨터는 현재 계속적인 연구단계에 있으며, IBM이나 구글 등에서 연구를 진행하고 있다고 해요. 
- 다만 속도가 지나치게 빠르다 보니 손쉽게 보안을 뚫어버리기도 한다고 해요. 하지만 의료시술 및 연구에 적절히 사용될 수 있으며 보완할 시 가능성이 무궁무진하기에 차세대 컴퓨터로 주목을 받고 있다고 합니다. 양자 컴퓨터가 보급형이 되면 이제 영화 Her에 나오는 AI도 꿈만은 아니겠죠?

 

02. 폰노이만 구조

- 컴퓨터의 구조는 다양한 방식으로 분류될 수 있는데, 폰노이만에 의해 그 구조가 깔끔하게 정리되었다고 합니다.

- 간략하게 요약하면, 폰노이만 구조1) CPU, 2) 메모리, 3) 프로그램 으로 이루어진다고 해요.

- 이 구조에 따르면 컴퓨터는 키보드와 같은 입력장치로부터 받아온 데이터를

   (1) CPU의 메모리를 통해 저장하는데, 

   (2) 레지스터에서는 변수와 같은 작은 데이터 및 중간처리과정에서의 데이터를 저장하고

        캐시에서는 자주 사용하는 데이터를 임시 저장해 빠르게 접근하며

        RAM(요즘엔 DRAM, DDP4)을 통해서는 전반적인 처리를 위한 데이터를 보관한다고 합니다.

   (3) 프로그램은 어떤 문제를 해결하기 위해 만들어진 명령문의 집합체를 의미하는 것으로, 앞서 말한 시스템 프로그램이나, 응용 프로그램이 이에 해당됩니다. 사용자는 프로그램을 통해 컴퓨터와 소통을 하는데요. 프로그램이 돌아가면서 사용자의 명령을 컴퓨터가 이해할 수 있게 0과 1로 변환하고 CPU의 연산장치(ALU)를 통해 명령을 처리합니다.

 

03. 비트(bit, 0과 1)와 비트논리연산(AND, OR, NOT)

- 폰노이만 구조에서 잠시 언급된 CPU의 연산장치(ALU)에는 마이크로 연산 곧,

   1) 논리연산을 수행하는 부분과 2) 산술연산을 수행하는 부분, 그리고 3) 시프트 연산을 수행하는 부분이 있습니다.

- 여기서 연산을 수행할 때에 "비트"라는 단위가 사용됩니다.

- 비트는 2진수 10을 나타내는 것으로, 스위치를 키고 끄는 것과 같이 ON과 OFF를 의미해요.

- 이 2진수의 수에 대해 비트 논리 연산을 수행할 수 있는데, 그것이 바로 AND/OR/NOT 연산입니다. 

- 컴퓨터 내부 회로는 AND, OR, NOT을 토대로 다시 NAND, NOR, XOR...을 만들어내는데요. 

- 논리회로를 엮어내어 산술연산을 만들 수도 있습니다.

 

[ 참고 : bit와 byte와 nibble ]

1 byte = 8 bits
1 nibble = 1/2 bytes = 4bits

* nibble은 영어로 '야금야금 먹다'라고 합니다. bite는 영어로 '한 입 베어 씹어 먹다'라는 뜻이라 해요.
  그러니 해석하면 byte는 '한 입'이니 1이고, nibble은 '야금'이니 1/2로 보면 쉬울 것 같아요.
  이런 소소한 재미. 버그도 그렇지만 공부하면 할 수록 과거 개발자들의 소박하며 귀여운 네이밍들을 볼 수 있네요.ㅎ
  

 

04. 비트 산술연산, 조합회로와 순차회로

- 앞에서 ALU에는 논리연산 외에도 산술연산을 수행한다고 이야기하였습니다. 그 중에서도 덧셈을 담담하는 것이 바로 아래의 '가산기'에요.

 

(1) 가산기(Adder)

- ALU에는 가산기라는 것이 있는데요. 논리회로를 조합해 반가산기 -올림을 제외한 한 자릿수 덧셈만 처리-를 만들고, 다시 추가으로 논리회로를 조합해 전가산기-올림까지 처리-를 만들면 제대로된 덧셈이 가능해집니다.

- 전가산기여러개를 묶으면 이젠 여러 자릿수를 계산할 수 있게 됩니다. 8개를 묶으면 8bit, 16개를 묶으면 16bit... 더 나아가서는 64bit의 자릿수를 처리할 수 있게 돼요.

 

(2) 발진기와 클럭

- 앞에서는 논리회로를 조합해서 만든 가산기(=덧셈기)를 말했다면, 이번엔 NOT을 만들어주는 발진기를 소개하려 합니다.

발진기(Oscilliator)는 전자회로를 통해 연속파의 교류신호를 발생하는 회로를 말하는데요. (말이 참 어렵다)

- 쉽게 말하면 0 -> 1 -> 0 -> 1.. 을 마치 매트로놈처럼 주기적으로 반복해서 만들어주는 녀석이라고 생각하면 됩니다.

- 다시, Oscilliator를 통해서 0이 들어오면 1을, 1이 들어오면 0을 반환하는 걸 하나의 사이클로 보는데요.

클럭(Clock)은 1초 동안 이 사이클이 움직이는 주파수를 말하는 것으로, 단위는 Hz로 표기됩니다.

- 클럭이 높을 수록 처리속도는 빨라지는데, 클럭을 높힌다고 다 놓은 것이 아닌 것이, 그만큼 발열량과 소비 전력이 커지는 단점이 있다고 합니다. 그래서 최근에는 클럭(클럭 - 비유 : 도로 제한 속도)을 높히기 보다는 멀티 코어(코어 - 비유 : 도로 차선) 또는 멀티 스레드를 통해 CPU 성능을 높이는 것을 추구한다고 해요.

 

(3) 플립플롭과 비트의 Write/Read

- 플립플롭(flip-flop)은 래치(latch)라고도 하며, NOR게이트를 조합해 만든 회로인데요, 최근에 스위치가 ON이었는지, OFF였는지를 알 수 있게 해주는 회로입니다.

- 결국 다시 말해, 플립플롭은 0 or 1 곧, 비트를 저장할 수 있는 회로를 말해요.

- 플립플롭의 종류는 R-S flip-flop, Level-triggered flip flop, D-type flip-flop, JK flip-flop 등 종류가 매우 다양하다고 합니다.

- 전원이 공급되는 한, 플립플롭은 상태의 변화를 위한 신호(클럭)이 발생할 때까지 현재 상태를 유지해요.

- 플립플롭을 여러개 묶으면 8bit latch를 만들수 있는데요, 8-to-1 selector와 3-to-8 decoder로 온전한 8 bit latch를 만들 수 있다고 합니다. 그리고 이 8bit latch가 우리가 말하는 RAM이라고 해요. RAM에서는 8-to-1 selector와 3-to-8 decoder를 통해 3개Address가 있으면 8개 중 하나의 비트선택해서 쓰거나 읽을 수 있다고 합니다.

- 이제 이 8 X 1 latch를 여러개 연결하게 되면 하나의 비트에서 여러개의 비트를 쓸 수 있는 m * n RAM array를 만들 수 있다고 해요. 그렇다면 64k RAM은 얼만의 데이터를 쓸 수 있을까요? 65536(2^16) x 8bits라고 합니다.

* 1 Megabytes = 1 Mega x 8 bits = 8 Megabits

[ 참조 : 어셈블리어 - 주소 배정 ]

MOV R1, #120     R1 <- 주소120 직접 지정
MOV R1, R2        R1 <- R2
MOV R1, 120      R1 <- 주소120의 데이터 넣기
MOV R1, @120  R1 <- 상대 주소 120 --- 위 세가지와 다르다.

 

(4) 누산기(Accumulator)와 레지스터

- 앞서 가산기에서 덧셈을 처리한다는 이야기를 하였고, 쭉쭉 내려와 RAM에서 특정 데이터를 저장하고 읽을 수 있다는 걸 이야기했어요. 이번에는 누산기에 대해 이야기를 할 건데요.

- 누산기산술 및 논리연산의 결과 또는 중간계산과정을 저장하는 레지스터를 말합니다.

- 구체적으로 들어가면 8-bit Adder와 8-bit Latch로 구성되어 있으며, Clear스위치가 눌리면 어떤 데이터든 기존 값을 삭제하고, Adder를 통해 덧셈이 이루어진다고 해요.

 

(5) Program Counter (PC) 

- Program Counter, 16-bit counter는 1씩 증가하는 조합논리회로를 말한다고 해요.

- 프로그램 카운터는 다음에 실행될 명령어가 들어갈 주기억장치의 주소를 기억하는 레지스터입니다.

Register Program Counter = 명령 계수기.
다음 수행될 명령어의 주소를 저장
Instruction Register = 명령 레지스터.
PC가 지정하는 번지에 기억된 명령어를 임시 저장
Status Register = 상태 레지스터.
CPU의 상태(flag) 정보 기억
프로세서의 상태나 연산 결과의 상태를 저장하기 위한 특수 목적의 레지스터
General Purpose Register = 범용 레지스터.
작은 데이터들의 임시 저장 공간. 연산 처리 및 데이터 주소를 지정

* 인터럽트시 PC는 1, R = 0이 된다. 

* Set(Preset) : 101010 | 111111 = 111111,  Clear(Reset) : 101010 & 000000 = 000000 

 

05. 어셈블리어(저급 언어)와 고급언어. 

- 어셈블리어는 기계어와 일대일 대응이 되는 저급 언어로, 컴퓨터 구조에 따라 사용하는 기계어가 달라집니다. 컴퓨터의 CPU마다 지원하는 오퍼레이션의 타입과 갯수, 레지스터의 타입과 갯수, 저장 데이터 표현 형태도 다 다르기 때문에 컴퓨터 제조업체에 따라서 어셈블리어도 다를 수 밖에 없어요.

- 어셈블리어는 니모닉이라고 하는 일련의 숫자를 단어로 바꿔준 언어를 사용합니다. (ex. MOV, LOAD, ADD, h)

- 어셈블리어의 한계를 극복하기 위해 고급언어가 등장하게 되었는데요,

- 이 중에서도 컴파일 언어는 소스 코드를 어셈블리어에서 기계어로 변환하는 "컴파일링"을 통해 먼저 메모리에 기계어로 번역된 코드를 올려두고 실행을 하는 언어를 말합니다. 예를 들어, C언어가 있죠. (자바도 컴파일 언어라고도 하는데, 사실상 컴파일과 인터프리터가 섞인 형태입니다)

- 반면 인터프리터 언어는 사전의 컴파일링 없이, 소스 코드를 한 줄씩 실행하며, 컴파일링을 진행하고 변환 코드를 실행하는 언어를 말합니다. 예를 들어, javascript, SQL, python, Ruby, 스크래치 등이 있습니다.

 

06. 다시 폰노이만. CPU의 구조와 실행과정

- 다시 폰노이만 구조로 돌아오면, 컴퓨터는 아래와 같이 구성됩니다.

[1] CPU : Controller Unit(Program Counter, 주소) + ALU (가산기 + 논리연산 + 레지스터)

[2] Memory

[3] 프로그램

 

- CPU의 기본 구조

PC(Program Counter) 다음 실행할 명령어 주소를 저장
IR(Intruction Register) 최근 인출한 명령어 보관
누산기 데이터 일시 보관
MAR(Memory Address Register) CPU가 메모리 참조 위해 보관하는 데이터 주소를 가진 레지스터
MBR(Memory Buffer Register) CPU가 메모리부터 읽거나, 저장할 데이터 자체를 보관하는 레지스터

 

- CPU의 기본 실행 구조

Instruction Fetch 실행할 명령어를 메모리에 읽어 CPU로 가져옴
Instruction Decode 인출한 명령어에 포함된 데이터를 가져오고 명령어를 해독
Instruction Execution 명령어 실행
Write Back 실행 결과 저장

* Instruction은 여기서 '명령어'라는 의미

 

- CPU의 명령어 구조 : opcode(사전 약속된 명령어) + operand(argument, 데이터)

 

 

 

[참조] 

- 마이크로 연산, https://devraphy.tistory.com/308?category=1014713 

- 레지스터 전송과 마이크로 연산 바로가기

- 클럭(Clock), https://soojong.tistory.com/entry/%ED%81%B4%EB%9F%ADClock

- 클럭과 코어와 스레드, 캐시메모리 https://library.gabia.com/contents/infrahosting/1227/

- 누산기 https://itpmw.tistory.com/578

🛎 2231 분해합

|  문제 

어떤 자연수 N이 있을 때, 그 자연수 N의 분해합은 N과 N을 이루는 각 자리수의 합을 의미한다. 어떤 자연수 M의 분해합이 N인 경우, M을 N의 생성자라 한다. 예를 들어, 245의 분해합은 256(=245+2+4+5)이 된다. 따라서 245는 256의 생성자가 된다. 물론, 어떤 자연수의 경우에는 생성자가 없을 수도 있다. 반대로, 생성자가 여러 개인 자연수도 있을 수 있다.
자연수 N이 주어졌을 때, N의 가장 작은 생성자를 구해내는 프로그램을 작성하시오.

|  입력

첫째 줄에 자연수 N(1 ≤ N ≤ 1,000,000)이 주어진다.

|  출력

첫째 줄에 답을 출력한다. 생성자가 없는 경우에는 0을 출력한다.

|  예제 입력

216

|  예제 출력

198

 

🔎 문제분석

어떤 수 N의 분해합을 구하는 거라면 쉬웠을 텐데, 분해합의 가장 작은 생성자(=곧, 어떤 수 N)를 찾는 문제라 난해했다.

- 이 문제는 분해합과 생성자의 관계를 파악하려 하면 더 힘들었다. 
  * 왜냐하면 생성자->분해합은 값이 하나로 떨어지지만
  * 분해합->생성자를 구하는 건 결과값이 여러 개일 수 있기 때문이다.
- 여기저기 알아보다보니 어차피 O(N) 속도라면, 1부터 1000000까지 돌리면서 분해합이 N인 경우를 찾기도 한 걸 봤는데,
  아무리 O(N)이라지만, 백만개를 다 돌리는 건 비효율적일 것 같아 다른 방법을 찾아보았다

 

(1) N의 생성자의 최대값은 N - 1이다.

주어진 분해합 값 N의 범위는 (1 ≤ N ≤ 1,000,000) 

==> 그렇다면 N의 생성자의 자릿수는 최대 6개 곧, 999,999가 된다. (생성자는 분해합 보다 적어도 1만큼 적을 것)

 

(2) N의 생성자의 최소치는 N - 54이다.

* M = N의 생성자

N = M + (M의 각 자리수에 대한 합) 

==> M의 각 자릿수의 최대치는 999,999이다.

==> N = 999,999 + (9 * 6)

==> (M의 각 자리수에 대한 합)의 최대치는 (9 * 6)이다.

==> M의 최소치는 곧, 54

N - (9 * 6) = M

 

(3) (1)~(2)를 종합해보았을 때, N의 생성자의 범위는 

N - 54 <= M <= N - 1

 

⌨️ 코드

 

|  순열 (permutation)

✏️ 개념 정리

(1) 팩토리얼 : 서로다른 N개의 수를 일열로 나열하는 전체 경우의 수

- 1~n까지 모든 자연수의 곱 (n!) --- 단, 0!은 1이다.

- n! = n*(n-1)...*1

 

(2) 순열 : 서로 다른 N개의 수에서 R개를 뽑아 나열하되, 순서대로 나열하는 경우의 수 

- 서로 다른 n개 중 r개를 선택하는 경우의 수 (순서 O, 중복 X)

- nPr = n! / (n-r)! = n(n-1)(n-2)....(n-r+1) (단, 0<r<=n)

 

(3) 중복 순열 : 서로 다른 n개 중 r개를 선택하는 경우의 수 (순서 O, 중복 O)

- nㅠr = n의 r 승

 

(4) 원 순열 : 원 모양의 테이블에 n개의 원소를 나열하는 경우의 수

n!/n = (n-1)!

 

💻 구현하기

[ 순열 구현 1_ 재귀 : 깊이에 따른 순차 교환 ]

✅  순열 : 서로다른 n개의 수에서 r개를 중복없이 순서를 고려하여 나열하는 것

 

✅  구현 방법

 

[입력]

서로 다른 n개의 수를 담은 배열과, 깊이 인덱스(depth), 배열의 길이(n), 선택하려는 갯수(r)를 인자로 받는다. 

*알고리즘이 시작되면, 깊이 인덱스(depth)는 0이다.

*깊이는 선택하려는 숫자의 인덱스를 의미한다.  

 

[처리]

현재 깊이(depth=0)와 깊이 인덱스부터(i=depth)~배열의 끝(i=n-1)까지 중 하나를 교환하고 깊이를 높혀줄 것이다. 

1. 현재 깊이 인덱스(depth=0)와 하나의 인덱스(i=depth=0)를 교환한다.

2. 깊이 인덱스를 하나 높혀준다.(depth=0+1=1)

2. 위의 1)~2) 과정을 반복한 뒤, 선택 가능 갯수를 초과할 때(depth == r) 탈출한다.

3. 탈출 후 더 낮은 깊이에서 정상교환이 이루어지도록 교환한 것을 재교환한다.

 

※ 그림으로 본 순열 알고리즘 모습

출처 :&nbsp;https://jksk0115.tistory.com/112

 

✅  구현 하기

void permutation(int[] arr, int depth, int n, int r) {

    if (depth == r) {
        for (int i = 0; i < r; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
        return;
    }

    for (int i = depth; i < n; i++) {
        swap(arr, depth, i);
        permutation(arr, depth + 1, n, r);
        swap(arr, depth, i);
    }

}

public void swap(int[] arr, int a, int b) {
    int tmp = arr[a];
    arr[a] = arr[b];
    arr[b] = tmp;
}

 

[ 순열 구현 2_ 재귀 :  교환 없이 추가배열을 통해 출력하기 ]

✅  순열 : 서로다른 n개의 수에서 r개를 중복없이 순서를 고려하여 나열하는 것

 

✅  구현 방법

 

[입력]

서로 다른 n개의 수를 담은 배열(int[] arr)과, 깊이 인덱스(depth), 배열의 길이(n), 선택하려는 갯수(r),

방문위치를 알려줄 배열(int[] visited), 출력 배열(int[] out)을 인자로 받는다.

*알고리즘이 시작되면, 깊이 인덱스(depth)는 0이다.

*깊이는 선택하려는 숫자의 인덱스를 의미한다.  

 

[처리]

현재 깊이(depth=0)에서 배열의 첫번째(i=0)~배열의 끝(i=n-1)까지 중 방문하지 않았던 곳을 출력배열에 출력할 것이다.

1. 현재 깊이 인덱스(depth=0) : 방문하지 않았던 곳(i=0)을 체크 후, 출력배열에 출력한다.(out[depth] = arr[i])

2. 깊이 인덱스를 하나 높혀준다.(depth=0+1=1)

2. 위의 1)~2) 과정을 반복한 뒤, 선택 가능 갯수를 초과할 때(depth == r) 탈출한다.

3. 탈출 후 더 낮은 깊이에서 정상출력이 가능하도록 방문했던 곳을 미방문상태(false)로 변경한다.

 

※ 그림으로 본 순열 알고리즘 모습

 

✅  구현 하기

void permutation(int[] arr, int depth, int n, int r, boolean[] visited, int[] out) {

    if (depth == r) {
        System.out.println(Arrays.toString(out));
        return;
    }

    for (int i = depth; i < n; i++) {
        if (!visited[i]) {
            visited[i] = true;
            out[depth] = arr[i];
            permutation(arr, depth + 1, n, r, visited, out);
            visited[i] = false;
        }
    }

}

'Computer Science > Basic Math' 카테고리의 다른 글

[기초수학] 점화식과 재귀함수  (0) 2022.07.11
[기초 수학] 조합  (0) 2022.07.11
[기초 수학] 집합과 경우의 수  (0) 2022.07.08
기초수학 총정리  (0) 2022.06.17

|  집합(Set)

✏️ 개념 정리 

특정 조건에 맞는 원소들의 모임

 

- 특징

중복되지 않은 수들을 한 곳에 모아놓는 것으로, 자바에서는 Set을 사용해 중복데이터를 거를 수 있다.

 

- 종류

종류 기호 HashSet 메소드
교집합 A ∩ B a.retainAll(b);
합집합 A ∪ B a.addAll(b);
차집합 A  -  B a.removeAll(b);
여집합 Ac -

 

💻 구현하기

[ HashSet 구현해보기 ]

 

|  경우의 수

✏️ 개념 정리 

어떤 사건에서 일어날 수 있는 경우의 가짓수 : n(A)

종류 내용 기호 예시
합의 법칙 A와 B의 분리된 집단에 관한 
어떤 사건의 경우의 수를 구할 때
* 단 두 집단의 합은 전체 집단이어야 한다.
n( B) = n(A) + n(B) - n(A ∩ B) - 남(5명)/여(3명) 집단이 있을 때,
나열할 수 있는 모든 경우의 수 
- 주사위 두 개를 던졌을 때,
전체 합이 3의 배수 또는 4의 배수가 나오는 모든 경우의 수
곱의 법칙 A와 B의 사건이 동시에 일어날 때
= A와 B의 사건이 연달아서 일어나며, 모든 사건이 끝나지 않았을 때
n(x B) = n(A) x n(B) - 주사위와 동전을 동시에 던졌을 때,
나올 수 있는 모든 경우의 수
- 주사위 두 개를 던졌을 때, 
하나는 3의 배수 하나는 4의 배수가 나오는 모든 경우의 수

 

(1) 약수 

- 6의 약수는 1,2,3,6

- N의 약수를 코드로 구할 때 루프를 사용한다면 N/2만큼만 루프를 돌려 나누어떨어지는 수를 구하고, 마지막으로 자기 자신을 더해주면 된다 (why? 2로 나누었을 때 절반까지만 나눠질것)

 

(2) 최대공약수

- A와 B의 약수 중 가장 큰 공통된 수

 

(3) 최소공배수 

- A와 B의 배수 중 가장 작은 공통된 수

- 최소공배수 = A x B / A와 B의 최대공약수 

 

 

💻 구현하기 

[ 경우의 수 - 합의 법칙과 곱의 법칙 ]

 

 

[ 약수, 최대공약수, 최소공배수 구하기 ]

 

 

'Computer Science > Basic Math' 카테고리의 다른 글

[기초수학] 점화식과 재귀함수  (0) 2022.07.11
[기초 수학] 조합  (0) 2022.07.11
[기초 수학] 순열  (0) 2022.07.08
기초수학 총정리  (0) 2022.06.17

|  개발 환경 구축

(1) 자바 환경 구축

- 자바는 JVM을 통해 모든 플랫폼(OS)에서 독립적으로 작동한다.

- 오라클사에서 JDK를 다운할 수 있다.(또는 openJDK 사용) 설치 사이트 바로가기

- 명령프롬프트(CMD)로 설치 환경 확인

- 시스템 환경 변수 설정

변수명 경로 예시
Path java.exe가 있는 경로 %JAVA_HOME%\bin
JAVA_HOME jdk폴더 경로 C:\myDev\jdk1.8.0_333

rf. 코딩 폰트 설치하기 : d2coding, jetbrains mono 폰트

rf. 맥에서 자바 설치하기 : [1] homebrew 설치 [2] 터미널에서 자바 설치

 

더보기

[ 시스템 환경 변수 - Path는 왜 넣는 걸까? ]

 

운영체제(OS)가 프로세스를 실행할 때 참조하는 값을 환경 변수라고 한다.

환경 변수에는 여러가지가 포함될 수 있는데, 이 중에서 Path는  말그대로 "경로"를 말한다.

Path를 통해서 한 번 경로를 입력해 두면, JDK 실행을 호출할 때 OS가 알아서 Path에 저장된 값를 참조한다.

 

※ 출처 : https://seol2.tistory.com/141

 

(2) 컴파일 및 실행

- 컴파일 및 실행과정

start ----------------> compiled ---------------> result
소스파일.java 컴파일러 : javac.exe 바이트코드 인터프리터 : java.exe 실행결과
class Main { //코드 } javac HelloWorld.java 000111101010001010...... java HelloWorld 안녕!

- 명령프롬프트 활용

- 에디터(IDE) 활용

에디터명 개인적인 비교 다운경로 사용자수 (*jlab 설문결과)
IntelliJ - 말끔한 UI
- 상세한 가이드 (ex. 메소드의 매개변수까지 자동 안내)
바로가기 약 40%
Eclipse - 각종 단축키를 활용하여 빠른 코딩 가능
  (ex. 만능해결사 ctrl + space)
- 워크 스페이스 구조를 상세히 안내
- 다소 올드한 UI와 복잡한 설정
바로가기 약 30%
Visual Studio - 과거에 자주 사용되던 에디터
- 다양한 플러그인을 사용할 수 있다
바로가기 그 외
이클립스를 설치하면 가장 먼저 해야할 것 : 인코딩 타입을 MS949 -> UTF-8로 바꾸어준다.
( 위치 : [Windows] - [Preference] - search : encoding, Workspace/CSS/HTML/JSP/XML 모두 UTF-8로 설정)
IntelliJ나 이클립스나 내장된 openJDK를 사용할 수 있다. * 되도록 오라클에서 JDK 설치 후 사용 권장
(단, IntelliJ는 openJDK를 선택해서 설치해야 한다. 이클립스는 기본적으로 설치된 openJDK가 있다)
이클립스 프로젝트에 JDK 경로 설정하기 (아래 '더보기' 선택)  

 

|  자바 확장자와 파일

구분 확장자 내용
자바 파일 소스파일.java, 바이트코드.class 소스코드, 이진코드
자바 아카이브 압축명.jar 패키지 포맷
: 자바코드 + 리소스 + 메타데이터 + 기타 
웹 아카이브 압축명.war 웹 패키지 포맷
: 서블릿 + JSP + 리소스(html,js,css...) + ...
엔터프라이즈 아카이브 압축명.ear application server에 배포하기 위해 jar과 war을 묶어놓은 파일

 

|  자바 구조와 문장

패키지 (선택) 첫글자 소문자로 표기, ' . '을 통해 상세 경로를 나타낸다. package java.util.Random
클래스 첫글자 대문자로 표기, 그 외는 식별자* 명명법을 따른다. class Main
    // 필드
    // 메소드
}

 

* 예약어 : 예약어는 이미 정의된 것 (ex. 기본형 변수, if/while.... )

* 식별자 : 사용자가 지정한 것 (대소문자 구분, 첫문자 숫자 불가, 공백사용 불가, 특수문자 $, _만 가능, 한글 사용 가능)

 

|  클래스

클래스 필드 변수 기본형 논리형/문자형/정수형/실수형
참조형 참조값(16진수의 주소)을 담는 변수
초기화블럭 변수 선언 및 초기화 후, 초기화 블럭을 통해 재초기화*
메서드 생성자 인스턴스 생성 시, 생성자 안에 인자를 넣어 변수 초기화 
일반 메서드 매개변수와 반환값을 갖는다
접근제어자* +, (default) all  

 

* 사용하는 접근제어자 표시 : all(모두 사용가능), +(public), #(protected) , (default), -(private) 

* 초기화 블럭 : static이 들어간 경우 클래스가 로딩될 때, 그렇지 않은 경우 인스턴스가 생성될 때마다 초기화를 한다. (일반적으로 리소스를 업로드할 때 쓴다.)

 

|  변수와 자료형

변수 구분 크기 범위 기본값
기본형 논리형 boolean 1byte false, true false
문자형 char 2byte 0 ~ 약 6만 '\u0000'
정수형 byte 1byte -128 ~ 127 0
short 2byte 약 -3만~약 3만 0
int 4byte 약 -20억 ~ 약 20억  0
long 8byte   0L
실수형 float 4byte   0.0f
double 8byte   0.0
참조형 -   JVM 크기에 따름
32bit(4byte)
/64bit(8byte)
  null

- 정수형에 대한 자세한 설명 (아래 '더보기')

더보기

(1) 진수 표현

int n10 = 10;   //10진수
int n2  = 0b10; // 2진수
int n8  = 010;  // 8진수
int n16 = 0xff; //16진수

// JDK 1.7부터는 '_'를 통해 자릿수를 표기할 수 있게 됐다.
n2 = 0b0000_0000_0000_0000_0000_0000_1010;

 

(2) 2진수의 음수 표현 (2의 보수)

//2의보수 [앞에서 마지막 전까지 반대, 마지막은 동일]
int n1 = 0b0000_0000_0000_0000_0000_0000_0000_1100; //12
int n2 = 0b1111_1111_1111_1111_1111_1111_1111_0100; //-12

//n1 + n2은 아래와 같다.
int n3 = 0b0000_0000_0000_0000_0000_0000_0000_0000; //0

(3) long과 short/byte

// short와 byte는 사칙연산 시 int로 반환된다. (내장된 연산장치가 int 단위로 반환하기 때문)
short n1 = 1;
short n2 = 2;
int res = n1 + n2;

// long의 표현
long n3 = 1L;

- 오버플로우와 언더 플로우

(1) 오버플로우 : 자료 범위를 넘어서 양수가 음수로 바뀌는 경우

(2) 언더플로우 : 자료 범위를 넘어서 음수가 양수로 바뀌는 경우

 

더보기
public class Test {
    public static void main(String[] args) {
        //int n = 30_0000_0000; --> 에러! 
        int n1 = 0b0111_1111_1111_1111_1111_1111_1111_1111; //int 최댓값 / int범위 : -2^31 ~ (2^31 - 1)
        int n2 = 0b1000_0000_0000_0000_0000_0000_0000_0000; //최댓값에 2진수 1을 더한 값
        System.out.println("n1 = " + n1); //n1 = 2147483647
        System.out.println("n2 = " + n2); //n2 = -2147483648 ---> 오버플로우

        int n3 = n2 - 1;
        System.out.println("n3 = " + n3); //n3 = 2147483647 ---> 이처럼 음수가 양수로 바뀌는 경우는 언더플로우

    }
}

- 문자형 : 유니코드에 따라 문자를 나타낸다

char c1 = '\u0000'; 
char c2 = '\uac00'; //'가'
//참조 : 한글 유니코드(UTF-8) https://jjeong.tistory.com/696

- 변수 표기법

표기법 어디에? 예시
파스칼 자바 : 클래스
c# : 변수, 클래스
class Car { }
Date, LocalDate, String, Scanner
카멜 자바 : 변수, 메소드 int speed, void speedTest(){}
스네이크 - 소문자 c, php void speed_test(){}
스네이크 - 대문자 SQL문법
자바 : 상수
SELECT * FROM member
final int MAX_SPEED
헝가리언  과거 변수 타입을 구분하기 위해 사용 int iMaxSpeed; int strUsername
케밥 html : class 구분
url 주소 표준 : '-'로 구분
<div class = "list-imgtxt">
http://www.naver.com/board-list //"_"가 아닌 "-"가 표준

 

|  연산자와 피연산자

- 단항 > 사칙연산 > 비교 > 대입, 크게 4가지의 방향으로 이해

- 아래의 어떤 연산자 보다도 가장 우선순위가 높은 것은 "(   )"

우선순위 연산자 이름 연산자 연산 방향
1 후위 단항 i++, i-- 왼쪽에서 오른쪽
2 전위 단항 ++i, --i, +val, -val, !
3 곱셈/나눗셈/나머지 *, /, %
4 덧셈 +
5 비트이동 >>, <<, >>>
6 관계 >, <, <=, >=, instanceOf
7 동등 ==, != 
8 비트 AND &
9 비트 배타적 ^
10 비트 OR |
11 논리 AND &&
12 논리 OR ||
13 조건 삼항 (조건) ? (참) : (거짓) 
14 대입 =, +=, -= .... 오른쪽에서 왼쪽

 

- 비트 연산자

연산자 이름 사용 의미
& 비트 AND op1 & op2 비트가 모두 1이면 결과는 1, 아니면 0
^ 비트 배타적 op1 | op2 비트가 적어도 하나가 1이면 결과는 1, 아니면 0
| 비트 OR op1 ^ op2 비트가 서로 다르면 결과는 1, 같으면 0
~ 보수(complement) ~op1 비트가 0이면 결과는 1, 0이면 1
// 2의 보수를 구하는 법
int i1 = i2;
int i2 = ~i1 + 1; //~ : 1의 보수, 1을 더하면 : 2의 보수

 

- 비트 이동

연산자 이름 사용 의미 비고*
>> signed left shift op1 >> op2 [기존부호] 오른쪽으로 op2비트만큼 이동 = op1 * 2^op2
<< signed right shift op1 << op2 [기존부호] 왼쪽으로 op2비트만큼 이동 = op1 / 2^op2
>>> unsigned left shift op1 >>> op2 [0으로 채움] 오른쪽으로 op2비트만큼 이동  

* 단, 변수의 Max크기까지만 가능하다. (ex. int 범위는 ~ 2^32까지)

 

- 형변환

(1) 자동 형변환 : 작은 범위에서 큰 범위의 자료형에 값을 넣을 때

(2) 명시적 형변환 : 큰 범위에서 작은 범위의 자료형에 값을 넣을 때. ex. int num = (int)(5/1.0);

 

- 연산 관련 예외

(1) ArithmeticException : (런타임 에러) 정수를 0으로 나눌 때

(2) Infinity : 실수를 0.0으로 나누면 무한대 

(3) byte와 short 산술 연산 : 모두 int로 변환되어 연산 수행

 

|  제어문과 반복문

구분 이름 코드 비고
제어문 조건문 if, if~else 자바는 if~else if~else가 없다
스위치문 switch~case default
반복문 - for, foreach
while, do while
break와 continue

 

|  개념

기수란? 수를 나타내는 데 기초가 되는 수. 

- 10진법에서는 0~9까지의 정수를 말하며, 2진법에서는 0~1까지 정수를 말한다.

 

|  기수 변환을 수행하는 프로그램

package _00_두잇;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class _01_기수변환 {
    //정수값 x를 r로 변환하여 배열 d에 아랫자리부터 넣어두고 자릿수를 반환한다.
	static int convert(int x, int r, char[] d) {
		int digits = 0;
		String dchar = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		
		//배열 안에 나눈 나머지를 하나씩 넣는다 
		while (x != 0) {
		  d[digits++] = dchar.charAt(x % r);
		  x = x / r;
		} 
		
		//배열의 역순이 변환한 진수값이다.
		for (int i = 0; i < digits/2; i++) {
			char tmp = d[i];
			d[i] = d[digits-1-i];
			d[digits-1-i] = tmp;
		}
		
		//변환한 수의 자릿수
		return digits;
		
	}
	
	public static void main(String[] args) throws Exception{
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		
		//변환하려는 수
		int num;
		//기수
		int jin;
		//변환한 수의 자릿수
		int digits;
		//변환 후 각 자리의 숫자를 넣어주는 문자 배열
		char[] cvArr = new char[32];
		
		System.out.print("변환하려는 수 : ");
		
		num = Integer.parseInt(reader.readLine());
		
		System.out.print("자릿수(2~36) : ");
		
		jin = Integer.parseInt(reader.readLine());
		
		digits = convert(num, jin, cvArr);
		
		System.out.print(jin+"진수로 ");
		for (int i = 0; i < digits; i++) {
			System.out.print(cvArr[i]);
		}
		System.out.print("입니다.\n");
		
	}
}

>> 결과

변환하려는 수 : 35
자릿수(2~36) : 2
2진수로 100011입니다.

 

[출처]

[자료구조와 함께 배우는 알고리즘 입문], BohYoh Shibata지음

+ Recent posts