Coding History

국비 지원 IT(웹앱개발) 취업반 강의 4일차

BlackBirdIT 2024. 5. 31. 23:12

드디어 내일이면 주말이라는 생각에 한시름 놓게 되지만 이 포스터에 주말동안은 유튜브 영상 정리든 문제풀이든 최소 하나씩을 올린다고 선언해 놓고 포스팅하겠다.

오늘 배운 것은 자료형(type)과 전위연산자, 후위연산자의 차이, 실수를 연산할 때 생기는 (부동소수점) 문제점, 배열과 문제 풀이였다.

  • 자료형(type)
  1. 기본형
  2. 참조형

두가지로 나뉘게 된다.

일단은 기본형이다. 자바에서 기본으로 제공하는 변수 저장소, 그래서 기본형 타입이고 사진으로 쉽게 정리한 것을 보면 이렇다.

자바 자료형

기본형 타입을 코드로 살펴보면

// 논리계열
boolean b = true; // or false

// 문자계열(사실 숫자가 저장됨, 왜냐하면 문자는 사실 숫자이다.)
char c = 'a'; // 'a' 는 사실 97 이다.

// 정수계열
byte bt = 1;
short s = 2;
int i = 3;
long l = 4L; // 자동형변환에 의해서 4라고 써도 됨

// 실수계열
float f = 5.5f;
double d = 5.5;

기본형은 변수 선언을 하면 실제 값을 변수에 저장한다. (스택에 쌓아둔다)

참조형은 작동방식이 조금 다르다. 참조형에 변수 선언을 하면 메모리(RAM)의 주소 값을 저장한다. 우리가 출력하거나 코드를 작성하면 그 주소 값을 통해서 주소안에 저장되어있는 객체를 사용하는 방식으로 작동한다.

메모리의 주소 값은 힙(Heap)이라는 공간과 연결하고 거기 존재하는 객체를 스택(Stack)으로 불러와서 사용하게 된다.

// 아래 기본형 변수들은 실제로 숫자를 가지고 있다.
boolean b = true;
char c = 'a'
byte bt = 1;
short s = 2;
int i = 3;
long l = 4L;
float f = 5.5f;
double d = 5.5;

// 기본형 변수 8종을 제외한 모든 변수는 참조형 변수이다.
// 참조형 변수에는 실체가 없다. 실체는 외부에 저장된다.
// 참조형 변수에는 실체를 조종할 수 있는 리모콘이 저장된다.
// 자바에서 리모콘의 크기는 모드 같다.
// 그래서 모든 참조형 변수의 크기는 8바이트 이다.(JVM 마다 다름, 딱히 중요하지 않음)
String str;
str = "안녕" + "하세요.";
// 엄밀히 말하면 str 에는 "안녕하세요." 가 들어있지 않다.
// str 에는 "안녕하세요." 라는 문자열 객체를 조종할 수 있는 리모콘이 들어있다.

String s1 = "하하";
String s2 = "하하하하하하하";

 // s1과 s2의 크기는 같다.
 // s1과 s2가 각각 가리키는 객체들은 서로 크기가 다르다.
  • 전위연산자와 후위연산자
    ```java
  • +i; //전위연산자
    i++; //후위연산자
    우리가 여태 작성한 코드중에 이런 형태를 몇번 접했었는데 이게 사칙연산의 위치에 따라서 전위연산 후위연산으로 구분해서 부른다. 
    

전위에 있냐 후위에 있냐의 차이로 값을 먼저 더하는지 뒤에 더하는지 정해진다.

사진으로 보면 조금 더 이해가 쉽다. 연산자의 위치를 잘못두면 생각했던 값이 안나올 수도 있으니 주의해야한다.

  • 부동소수점

강사님이 부동소수점 자체는 자세하게 알 필요가 없다고 하셨다. java든 컴퓨터 언어로 실수를 계산할 때 생길 수 있는 문제중 하나라고 주의 하라고 하셨다. 컴퓨터는 이진수를 사용하는데, 그 이진수 때문에 생기는 문제라고 하셨다.

위의 사진과 같이 부등호의 영역, 지수의 영역, 가수의 영역이 차례로 나뉘는데, 소수점으로 넘어가면서 이진법때문에 그 0과 1의 개수가 23비트를 넘어가면서 문제가 발생한다고 한다.

  • 배열

여기서 조금 애를 먹었다. 배열 자체를 이해하지 못한게 아니고 그냥 문제 풀이에서 이상한 곳에서 막혔다..
쓸데 없는 말은 치우고 일단 배열에 대해서 알아보자.

int[] array = new int[];

이 형태가 배열을 불러오는 코드이고, 자료형은 참조형이다. 참조형이니 당연히 위의 참조형 방식대로 작동한다.

내가 풀었던 문제는 코드업의 기초문제풀이 - 1094 (이상한 출석번호 부르기 2)였고 문제는 이렇다.

//정보 선생님은 수업을 시작하기 전에 이상한 출석을 부른다.
//
//선생님은 출석부를 보고 번호를 부르는데,
//학생들의 얼굴과 이름을 빨리 익히기 위해 번호를 무작위(랜덤)으로 부른다.
//
//그리고 얼굴과 이름이 잘 기억되지 않는 학생들은 번호를 여러 번 불러
//이름과 얼굴을 빨리 익히려고 하는 것이다.
//
// 출석 번호를 n번 무작위로 불렀을 때, 각 번호(1 ~ 23)가 불린 횟수를 각각 출력해보자.

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        int n, i;
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        int[] arr = new int[n];
        for(i = 0; i <= n; i++){
            arr[i] = sc.nextInt();
        }
        for(i = n - 1; i >= 0; i--){
            System.out.printf("%d", arr[i]);
        }
    }
}

우선 정답은 위의 코드고 내가 문제를 겪은 부분은 배열 때문인데,

int[] arr = new int[n]; //배열 선언과 배열의 int 값에 입력 값 n번만큼 객체를 생성하겠다는 코드이다.

이게 왜 문제가 됐냐면, 배열의 규칙 때문이다.

int[] arr = new int[3]; // 배열을 선언했고 객체를 세개 생성한다는 뜻이다.

// 그럼 Heap 구역에 int 값을 저장할 수 있는 객체가 3개가 생성이 되는데.
// 순서가 1부터가 아니고 0부터 생성이 된다. 이게 java의 절대 규칙인데 내가 이 사실을 몰랐다.

// Ex int[] arr = new int[3];에 생성된 객체
    int [0]
    int [1]
    int [2] // 이렇게 세개가 생성되는 것.

내가 저지른 실수를 코드로 위의 코드와 비교해보자.

int n, i;
Scanner sc = new Scanner(System.in);
n = sc.nextInt(); // n에 변수 입력을 하면
int[] arr = new int[n]; // 입력값만큼 객체 생성하도록 코드를 짰다.
for(i = 1; i <= n; i++){ // 여기서부터 문제가 발생하는데 배열은 0부터 시작이다. 근데 i의 값이 벌써 1이다.
arr[i] = sc.nextInt();
}
for(i = n; i >= 1; i--){ //여기도 마찬가지 배열의 값에 3이 들어간다면 0, 1, 2 객체가 생성이 되니 n - 1을 해줘야 
// index 범위안에 존속하게 된다.
System.out.printf("%d", arr[i]);
}

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 10
at org.example.Main.main(Main.java:22)
변수 설정 하나 잘못해서 이런 오류가 계속 생겼고 나는 배열의 규칙을 제대로 파악하기 전까지 이 문제를 계속 해결하지 못했다.

그래도 구글링의 힘으로 어찌저찌 해결했고.. 해결하니까 되게 후련했다. 이 맛에 문제를 푸는구나 싶었고 엄청 별 것 아닌 문제로 혼자 계속 고민하던게 좀 바보 같다고 느껴지기도 했다.

아무래도 재미를 붙힐 수 있을 것 같다. 아직 배우고 있는게 언어에서 걸음마조차 안될지도 모르지만 나는 어찌됐던간에 시작했다. 부디 끝까지 잘 해내는 나의 모습을 보고 싶다.