728x90
제네릭의 기본 사용

제네릭의 기본 사용

  • 제네릭 : 자료형을 다루는 메소드나 클래스를 컴파일 시점에서 검사하여 적절한 자료형을 선택
    • 앵글 브라켓(<>) 사이에 자료형을 선언
    • 자료형을 대표하는 형식 매개변수로 T를 사용
class Box(a : Int) //원래의 클래스 선언 /////////// class Box<T>(a:T) //제네릭 클래스 선언 - 모든 자료형을 받을 수 있음 fun main() { val box1 = Box(1) //Box<Int>로 초기화 val box2 = Box("kim") //Box<String>으로 초기화 }

제네릭 함수

  • 제네릭 함수 : 함수나 메소드 앞에 지정
fun <T> genericFun(arg : T) : T? { ... } //T는 순서대로 형식 매개변수, 매개변수 자료형, 반환 자료형 fun <K, V> genericFun(key : K, value : V) : Unit {...} //형식 매개변수가 여러개인 경우 //배열의 인덱스 찾기 fun <T> find(a:Array<T>, Target : T) : Int { for (i in a.indices) //a.indice : a의 인덱스 반환 (0..n) { if(a[i] == Target) return i } return -1 } fun main() { val arr1: Array<Int> = arrayOf(1,2,3,4) println(find(arr1, 2)) //1 반환됨 } //람다식을 이용한 반환형 연산식 결정 fun <T> add(a:T, b:T, op : (T,T)->T):T { return op(a,b) } fun main() { val result = add(2, 3, {a, b -> a+b}) //람다식으로 2+3 반환됨 println(result) //5 출력 }
  • 함수의 형식 매개변수 제한하기 : <T:자료형>으로 선언하여 제한 가능
    • 함수 호출 시 해당 자료형으로 선언해주어야 함(<자료형>) - 만족하지 않을 경우 오류 발생
  • 가변성
    • 형식 매개변수가 클래스 계층에 미치는 영향 정의
    • 상위 클래스가 하위 클래스를 수용할 수 있음
      • ex. Number(정수, 실수를 모두 포함) > Int, Int?(Nullable) > Int

가변성의 유형

  • 무변성 : C와 C<T'>는 무관
    • 코틀린에서는 별도 지정이 없으면 형식 매개변수는 무변성
  • 공변성 : T'이 T의 하위 자료형이면, C<T'>는 C의 하위 자료형
    • <Out T`>로 선언
    • 하위 자료형이 상위 자료형으로 캐스팅됨
  • 반공변성 : T'이 T의 하위 자료형이면, C<T'>는 C의 상위 자료형
    • <in T`>로 선언
    • 상위 자료형이 하위 자료형으로 캐스팅됨

자료형 프로텍션

  • 선언 지점 변성 : 클래스 자체에 가변성 지정 / 클래스 사용 시 자료형 지정 필요가 없음
  • 사용 지점 변성 : 클래스 생성 등 사용 위치에서 가변성을 지정
class Box<T>(var : item : T) { fun <T> printObj(box : Box<out Animal>) // Box를 사용할 때 가변성을 결정 { val obj : Animal = box.item //out이므로 getter가 동작 box.item = Animal() //out이므로 setter는 동작하지 않음 //자료형 프로텍션(out으로 선언)에 의해 안전성 보장 } }
  • 스타 프로젝션 : in/out 선언 없이 추후 겱정
    • <*>으로 선언
    • 자료형이 결정된 후에는 그 자료형만 사용 가능하도록 제한

배열

  • 데이터의 연속적 나열
    • arrayOf(), Array() 생성자로 생성
    • arrayOfNulls() : 빈 배열
    • 배열은 객체이므로 Heap에 저장됨
val numbers = arrayOf(1, 2, 3, 4) for (element in numbers) println(element)
  • 다차원 배열 : 배열의 배열
val array1 = arrayOf(1, 2, 3) val array2 = arrayOf(4, 5, 6) val array3 = arrayOf(7, 8, 9) val arr2d = arrayOf(array1, array2, array3) /* 1 2 3 4 5 6 7 8 9 */ //변수 선언 없이 2차원 배열 val arr2d = arrayOf(arrayOf(1, 2, 3), arrayOf(1, 2, 3), arrayOf(1, 2, 3)) /* 1 2 3 1 2 3 1 2 3 */
  • 자료형이 제한된 배열
    • arrayOf<자료형>(...)
    • charArrayOf(), booleanArrayOf(), ... 등 (자료형)ArrayOf()으로 작성
  • 배열 요소에 접근
    • 읽기
      • arr.get(인덱스) : 게터를 이용
      • arr[인덱스]
    • 쓰기
      • arr.set(인덱스, 값)
      • arr[인덱스] = 값
  • Array (요소 개수, 초기값) : 표현식을 이용한 배열 생성
    • 2씩 늘어나는 정수 배열 : Array(5, {i -> i*2}) (람다식으로 초기값 설정 가능)
    • 1000개의 null 배열 : arrayOfNulls(1000)
    • 1000개의 0배열 : Array(1000, {0})
  • 생성된 배열은 고정
    • 새롭게 할당 : arr.plus(요소)
    • 범위를 잘라내어 새 배열 생성 : arr.sliceArray(0..2)
  • 배열의 순환
    • forEach {element -> 식} : 요소별로 순환
    • forEachIndexed {i, e -> 식} : 인덱스, 요소를 배열에서 받아서 식 처리
    • Iterator 사용 : arr.iterator().next() (다음 index 반환)

배열의 정렬

  • 코틀린 Array는 기본적인 정렬을 제공
  • 정렬 배열 반환
    • sortArray() : 오름차순 정렬
    • sortArrayDescending() : 내림차순 정렬
  • 원본 배열 정렬
    • sort() : 오름차순
    • sortDescending() : 내림차순
  • 배열 필터링
    • filter(람다식) : 원하는 데이터를 선택 가능
    • minBy, maxBy, 필드보다 작은/큰 값
    • flatten : 다차원 배열을 평탄화

문자열의 기본

  • 문자열은 배열의 일종으로, 불변값으로 생성
    • 참조 메모리는 변경되지 않음
    • 새로운 문자열 대입 시 기존 문자열은 Garbage Collector에 의해 제거
  • 문자열 추출, 병합
    • String.substring(인덱스 범위) : 범위 내 문자를 String으로 반환
    • CharSequence.subSequence(인덱스 범위) : Charsequence로 반환
    • 병합 : 문자열은 덧셈을 통해 이어붙일 수 있음 ("ab"+"c" -> "abc")
  • 문자열 비교
    • a.compareTo(b) : a,b가 같으면 0, a가 작으면 양수, 그렇지 않으면 음수
      • 각 위치에 있는 문자열의 숫자값을 비교
    • a.compareTo(b, true) : 대소문자에 무관하게 비교
  • StringBuilder(문자열)
    • 문자열 공간을 더 크게 잡음
    • 작은 범위의 요소 변경이 용이 / 처리가 늦고, 변경이 없는 경우 메모리 낭비
    • 문자열 변경이 잦은 경우 사용
  • 그 외 메소드
    • append(문자열) : 문자열 뒤에 이어붙임
    • insert(인덱스, 문자열) : 해당 인덱스부터 문자열 이어붙임
    • delete(a, b) : [a, b-1]의 범위 문자 삭제
    • toLowerCase / toUpperCase : 소/대문자 변경
    • split(기준) : 기준 문자를 기준으로 한 문자열 분리
    • trim() : 앞뒤 공백 제거
728x90
728x90
추상 클래스 (abstract class)

추상 클래스 (abstract class)

  • 구현할 클래스의 명세를 정의 : 하위 클래스에서 구체 사항을 구현
    • 실제로 구현되지는 않음
    • ex. abstract class Vehicle : 하위 클래스로 차량의 클래스인 차량, 오토바이 등을 구현
    • open 키워드 없이 상속 가능
abstract class Vehicle(val name : String, val color : String, val weight : Double) //primary constructor 속 프로퍼티는 abstract가 아님 { abstract val maxSpd : Double //추상 프로퍼티 : 하위 클래스에서 override해야 함 abstract fun start() abstract fun stop() // 추상 메소드 : 하위 클래스에서 구현해야 함 fun display() { println("$name / $color / $weight") }//비 추상 메소드 : 하위 클래스 모두가 해당 구현물을 갖게 됨 } class Car(name : String, color : String, weight : Double, override val maxSpd : Double) : Vehicle(name, color, weight) //상속 선언(maxsPd override 포함) { override fun start() { println("car start") } override fun stop() { println("car stop") } }
  • object를 이용한 추상 메소드 구현
abstract class Printer { abstract fun print() } val myPrinter = object : Printer() { override fun print() println("출력!")//하위 클래스 선언 없이 임시로 추상 메소드 구현 가능 }

인터페이스

  • 해야 하는 작업에 대한 추상적 명세
    • 클래스가 아니므로 다중 상속 가능
    • 강한 연관을 갖지 않음
interface Pet //인터페이스 상속 시 ': 인터페이스명' 추가 { //abstract 없이도 프로퍼티/메소드 선언됨 var category : String fun feeding() //다만 메소드는 내용 작성 시 일반 메소드로 동작 fun patting() { println("Keep patting!") } } class Cat(override var category : String) : Pet { override fun feeding() { println("Feed cat tuna!") } //patting은 인터페이스에서 선언되었으므로 오버라이드가 없어도 됨 }

데이터 클래스

  • 데이터 전달을 위한 객체 DTO(Data Transfer Object)
    • 자바에서는 POJO(Plain Old Java Object)
    • 구현 없이 데이터를 표현
    • 데이터를 접근하는 게터/세터 포함
  • 코틀린의 데이터 클래스 : 프로퍼티 = 필드 + 게터, 세터
  • 자동 생성 메소드
    • 게터, 세터
    • 비교를 위한 equals(), 키를 위한 hashCode()
    • 프로퍼티를 문자열로 보여주는 toString()
    • 객체 복사를 위한 copy()
    • 프로퍼티에 상응하는 component1(), component2(), ...
  • 선언 방식 : data class 이름(프로퍼티)
    • 주 생성자는 최소 하나의 매개변수를 가져야 함
    • 주 생성자의 모든 매개변수는 val, var 프로퍼티여야 한다
    • 데이터 클래스는 abstract, open, sealed, inner 키워드를 쓸 수 없음
data class Customer(var name : String, var email : String) { var job : String = "unknown" constructor(name : String, email : String, __job : String) : this(name, email) { job = __job } // 부 생성자 : 프로퍼티 선언 init { // init : 간단한 로직 선언 가능 } } val cus1 = Customer("kim", "kim@mail.com") val cus2 = Customer("kim", "kim@mail.com") println(cus1 == cus2) //동등성 비교, true 반환 println(cus1.equals(cus2)) //위와 동일 println("${cus1.hashCode(), ${cus2.hashCode()}}") // 고유값 동일 - 두 객체의 값이 동일하므로 참조하는 위치도 동일함 val cus3 = cus1.copy(name = "alice") // cus1 내용을 복사하면서 name만 새 값을 대입
  • 디스트럭처링(destructuring) : 객체의 프로퍼티를 개별 변수로 분해
val (name, email) = cus1 val (_, email) = cus1 // 특정 프로퍼티가 필요 없는 경우 val name = cus1.component1() //cus1의 1번째 component(name) 반환 val customers = listOf(cus1, cus2) //DTO가 많은 경우 리스트화 후 반복문 사용 for((name, email) in customers)

내부 클래스와 중첩 클래스

  • 코틀린의 내부 클래스
    • 중첩(Nested) 클래스 : 객체 생성 없이 이용 가능
      • 외부 클래스 생성 없이 내부의 nested 객체를 생성할 수 있음
      • 외부 클래스에 companion object를 갖고 있을 경우 해당 객체에 접근 가능
    • 이너(inner) 클래스 : 필드, 메소드와 연동하는 클래스(inner 키워드 필요) - 외부 클래스 프로퍼티에 접근 가능
      • 클래스 내에 키워드 없이 선언 시 nested class로 선언됨, 내부 클래스는 외부에 접근이 불가능하게 됨
      • 바깥 클래스의 private 멤버도 접근 가능
    • *익명 객체 : 일회용 객체 선언을 위해 object 키워드 사용

지역 클래스와 익명 클래스

  • 지역 클래스(Local Class)
    • 특정 메서드 블록이나 init블록과 같이 그 안에서만 유효한 클래스
      • 블록 범위 내에서는 사용되지 않음
class Smartphone(val model:String) { fun powerOn() : String class Led(val color : String) { fun blink() : String = "Blink $color on $model" }//지역 클래스 - 외부 프로퍼티에 접근 가능 val powerStatus = Led("Red") return powerStatus.blink() }
  • 익명 클래스(Anonymous Class)
    • 일회적으로 객체를 생성해 사용
    • 메모리 효율 혹은 개발 속도(오버라이딩 구현) 면에서 사용

실드 클래스와 열거형 클래스

  • 실드(Sealed) 클래스
    • sealed 키워드를 사용
    • 그 자체로는 추상 키워드와 같이 객체 생성은 불가
    • 기본 생성자는 private, 그 외에는 불허
    • 같은 파일 내에서만 상속 가능
    • 블록 내의 클래스는 필요한 경우 open 키워드로 선언하여 상속 가능
    • 주로 상태의 정의와 관리에 사용
sealed class Result { open class Success(val message : String) : Result() //해당 클래스는 상속 가능 class Error(val code : Int, val message : String) : Result() } class Status : Result() // 같은 파일에서만 상속 가능 class Inside : Result.Success("Success") // 내부 클래스 상속
  • 열거형 클래스(enum class)
    • 여러 상수를 선언하고 조건에 따라 값을 선택 가능
    • 동일한 자료형의 상수 나열 가능
enum class 이름(생성자) { 상수1(값), 상수2(값), 상수3(값), ... //값은 선택 가능 }
  • 어노테이션 클래스
    • 코드에 부가정보 추가
    • @기호를 이용하여 사용
    • 컴파일러나 프로그램 실행 시 사전 처리
      • @Test : 유닛 테스트
      • @JvmStatic : 자바 코드에서 컴패니언 객체 접근
728x90
728x90
Lagrange InterPolation

Lagrange Interpolation

Weierstrass Approximation Theorem

  • Algebric Polynomial
    • 임의의 f(x)에 대한 근사식
    • Pn(x)=anxn+an1xn1+...+a0P_n(x)=a_nx^n+a_{n-1}x^{n-1}+...+a_0
    • 함수 f가 [a, b]에서 연속할 경우, f(x)P(x)<ϵ|f(x)-P(x)|<\epsilon인 P가 존재
    • 오차 ϵ\epsilon이 작아질수록 차수 n은 증가

Taylor Polynomial

  • 함수 f가 x=a에서 (n+1)번 미분 가능할 경우
    • f(x)=f(0)+f(a)(xa)+f(a)2(xa)2+...+fn(a)n!(xa)n+fn+1(ψx)(n+1)!(xa)n+1f(x)=f(0)+f'(a)(x-a)+\frac{f''(a)}{2}(x-a)^2+...+\frac{f^n(a)}{n!}(x-a)^n+\frac{f^{n+1}(\psi_x)}{(n+1)!}(x-a)^{n+1}
    • n+1차항 : Taylor 급수의 error
    • f(x)=P(x)=f(0)+f(a)(xa)+f(a)2(xa)2+...+fn(a)n!(xa)nf(x)=P(x)=f(0)+f'(a)(x-a)+\frac{f''(a)}{2}(x-a)^2+...+\frac{f^n(a)}{n!}(x-a)^n으로 근사할 수 있다
    • ψx\psi_x : x ~ a 사이의 임의 값
  • ex. x=0에서의 f(x)=exf(x)=e^x
    • f는 미분해도 모두 동일한 함수
    • x=0 대입시 f=1
    • ex1+x+x22!+...+xnn!\therefore e^x\simeq1+x+\frac{x^2}{2!}+...+\frac{x^n}{n!}
    • error : eψx(n+1)!xn+1\frac{e^{\psi_x}}{(n+1)!}x^{n+1}
  • Taylor Polynomal의 수렴 반경
    • ex. 1/x의 taylor polynomal : 전개할수록 오차가 커짐
    • 1/x를 x=1에서 전개 시 x는 0 ~ 2를 벗어날 수 없음(대칭성)
    • 수렴 범위를 벗어날 경우 taylor polynomal은 발산
  • Weierstrass theorem : P가 taylor 급수 ≠ P(x)가 수렴한다

Lagrange Polynomial

  • Polynomal Interpolation(1차 식으로 근사)
    • 점 [x0, y0], [x1, y1]의 경우 P1(x)=y1y0x1x0(xx0)+y0P_1(x)=\frac{y_1-y_0}{x_1-x_0}(x-x_0)+y_0
  • Lagrange Polynomial : Polynomial Interpolation을 구조화
    • L0(x)=xx1x0x1, L1(x)=xx)0x1x0L_0(x)=\frac{x-x_1}{x_0-x_1},\ L_1(x)=\frac{x-x)0}{x_1-x_0}로 정의
    • P1(x)=f(x0)L0(x)+f(x1)L1(x)P_1(x)=f(x_0)L_0(x)+f(x_1)L_1(x)
  • 2차 Lagrange Pilynomial : 점 [x0, y0], [x1, y1], [x2, y2]
    • L0(x)=(xx1)(xx2)(x0x1)(x0x2), L1(x)=(xx0)(xx2)(x1x0)(x1x2), L2(x)=(xx0)(xx1)(x2x0)(x2x1)L_0(x)=\frac{(x-x_1)(x-x_2)}{(x_0-x_1)(x_0-x_2)},\ L_1(x)=\frac{(x-x_0)(x-x_2)}{(x_1-x_0)(x_1-x_2)},\ L_2(x)=\frac{(x-x_0)(x-x_1)}{(x_2-x_0)(x_2-x_1)}
    • P2(x)=f(x0)L0(x)+f(x1)L1(x)+f(x2)L2(x)P_2(x)=f(x_0)L_0(x)+f(x_1)L_1(x)+f(x_2)L_2(x)
  • 자기 자신을 제외한 나머지 점으로 규칙성을 갖는 식 수립 가능
    • n+1개 점 > n차 Lagrange Polynomial
    • general case : n차 다항식의 k번째 점의 lagrange basis Ln,k(x)L_{n,k}(x)
      =Πxxnxkxn=(xx0)...(xxk1)(xxk+1)...(xxn)(xkx0)...(xkxk1)(xkxk+1)...(xkxn)=\Pi\frac{x-x_n}{x_k-x_n}=\frac{(x-x_0)...(x-x_{k-1})(x-x_{k+1})...(x-x_n)}{(x_k-x_0)...(x_k-x_{k-1})(x_k-x_{k+1})...(x_k-x_n)}

InterPolating Error bound

  • Lagrange Polynomial로 구한 근사식
    • f(x)=P(x)+fn+1ζ(x)(n+1)!(xx0)(xx1)...(xxn)f(x)=P(x)+\frac{f^{n+1}\zeta(x)}{(n+1)!}(x-x_0)(x-x_1)...(x-x_n)
      • ζ(x)\zeta(x)는 a~b 사이의 임의의 점
    • P(x)=f(x0)Ln,0(x)+...+f(xn)Ln,n(x)=k=0nf(xk)Ln,k(x)P(x)=f(x_0)L_{n,0}(x)+...+f(x_n)L_{n,n}(x)=\sum^{n}_{k=0}f(x_k)L_{n,k}(x)
    • Error : fn+1ζ(x)(n+1)!(xx0)(xx1)...(xxn)\frac{f^{n+1}\zeta(x)}{(n+1)!}(x-x_0)(x-x_1)...(x-x_n)
  • 증명 과정
    • xxkx\not ={x_k}라고 할 때, g(t)g(t)함수를 다음과 같이 정의
      • g(t)=f(t)P(t)[f(x)P(x)](tx0)(tx1)...(txn)(xx0)(xx1)...(xxn)=f(t)P(t)[f(x)P(x)]Πi=0n(txi)(xxi)g(t)=f(t)-P(t) - [f(x)-P(x)]\frac{(t-x_0)(t-x_1)...(t-x_n)}{(x-x_0)(x-x_1)...(x-x_n)}=f(t)-P(t) - [f(x)-P(x)]\Pi^n_{i=0}\frac{(t-x_i)}{(x-x_i)}
    • P는 f의 interpolation이므로 모든 x값에 대해
      g(xn)=f(xn)P(xn)=0g(x_n)=f(x_n)-P(x_n)=0 (PiPi항은 분자 식에 의해 0)
    • Rolle's Theorem : n개 점에서 함수가 0이면, n-1차 미분의 값이 0인 점이 존재
      • g(t)는 x,x0,x1,...,xnx, x_0, x_1, ..., x_n의 구간으로 n+2개의 함수가 0인 점이 존재하므로, n+1차 미분이 0인 점 ζ\zeta가 존재
      • fn+1(ζ)Pn+1(ζ)[f(x)P(x)]dn+1dtn+1[Πi=0ntxixxi]t=ζf^{n+1}(\zeta)-P^{n+1}(\zeta)-[f(x)-P(x)]\frac{d^{n+1}}{dt^{n+1}}[\Pi^n_{i=0}\frac{t-x_i}{x-x_i}]_{t=\zeta}
      • P는 최대 n차식이므로 Pn+1=0P^{n+1}=0
    • gn+1(ζ)=0=fn+1(ζ)0[f(x)P(x)](n+1)!Πi=0n1xxig^{n+1}(\zeta)=0= f^{n+1}(\zeta)-0-[f(x)-P(x)](n+1)!\Pi^n_{i=0}\frac{1}{x-x_i}
      • (txi)(t-x_i)는 n+1차항이므로 n+1번 미분하면 (n+1)!
    • 위 식을 f(x)에 대해 정리하면
      f(x)=P(x)+fn+1ζ(x)(n+1)!(xx0)(xx1)...(xxn)f(x)=P(x)+\frac{f^{n+1}\zeta(x)}{(n+1)!}(x-x_0)(x-x_1)...(x-x_n)
    • 즉 원래 식과 근사식의 차 f(x)P(x)=fn+1ζ(x)(n+1)!(xx0)(xx1)...(xxn)f(x)-P(x)=\frac{f^{n+1}\zeta(x)}{(n+1)!}(x-x_0)(x-x_1)...(x-x_n)가 Error값이 됨
      • 최대 오차는 maxfn+1(ζ(x))(n+1)!max(xx0)(xx1)...(xxn)max|\frac{f^{n+1}(\zeta(x))}{(n+1)!}|\cdot max|(x-x_0)(x-x_1)...(x-x_n)|
728x90
728x90
Cubic Spline Interpolation

Cubic Spline Interpolation

Piecewise Polynomial

  • 임의의 함수 y=f(x)의 근사
  • 일정 간격으로 1차(직선)으로 근사 (linear interpolation) 시의 문제점
    • 각 근사 구간의 교점마다 그래프가 각진 형태로 나타남
    • 근사식의 오차가 크게 나타남
  • 2차 식으로 근사 시
    • 그래프의 오차는 다소 줄어듦
    • 구간 접점의 문제는 해결 x
  • n차 미분이 가능할수록 구간별 연결이 부드럽지만, 과할 경우 진동 문제 존재

Cubic Spline Condition

  • 3차 다항식 aj+bj(xxj)+cj(xxj)2+dj(xxj)3a_j+b_j(x-x_j)+c_j(x-x_j)^2+d_j(x-x_j)^3를 구간별로 분할한 함수 S, S1, ..., Sj,Sj+1, Sn2, Sn1S,\ S_1,\ ...,\ S_j, S_{j+1},\ S_{n-2},\ S_{n-1}
  • 각 구간별 함수의 접점이 연속(Piecewise)할 것을 요구
  • 연결점에서 연속되기 위한 조건 (for all j=0, 1, .. ,n-1)
    • Sj(xj+1)=f(xj)S_j(x_{j+1})=f(x_j)
    • Sj+1(xj+1)=f(xj+1)S_{j+1}(x_{j+1})=f(x_{j+1})
    • 1차 미분 : Sj=Sj+1S'_j=S'_{j+1}
    • 2차 미분 : Sj=Sj+1S''_j=S''_{j+1}
  • 전체 함수의 개수가 갖는 계수는 총 4n개이므로
    • 2n개의 함수 연속 조건
    • n-1개의 1, 2차 미분 연속 조건
    • 총 4n-2개의 연속 조건을 갖게 됨 (2개가 더 있어야 계수의 계산이 가능)
    • 이를 위해 2개 조건을 더 추가 (Boudary Condition)
  • Natural Boundary Condition : S(x0)=S(xn)=0S''(x_0)=S''(x_n)=0 (기울기는 있으나 휨은 없음)
    • free boudary condition이 있는 곡선을 natural spline이라고 함
  • ex. (1, 2), (2, 3), (3, 5)를 지나는 natural cubic spline을 구할 것
    • [1, 2]의 구간에서 S0(x)=a0+b0(x1)+c0(x1)2+d0(x1)3S_0(x)=a_0+b_0(x-1)+c_0(x-1)^2+d_0(x-1)^3
    • [2, 3]의 구간에서 S1(x)=a1+b1(x2)+c1(x2)2+d1(x2)3S_1(x)=a_1+b_1(x-2)+c_1(x-2)^2+d_1(x-2)^3
    • f(1)=2=a0, f(2)=3=a0+b0+c0+d0f(1) = 2 = a_0,\ f(2)=3=a_0+b_0+c_0+d_0
    • f(2)=3=a1, f(3)=5=a1+b1+c1+d1f(2) = 3 = a_1,\ f(3)=5=a_1+b_1+c_1+d_1
    • S0(2)=S1(2)b0+2c0+3d0=b1S'_0(2)=S'_1(2)\rarr b_0+2c_0+3d_0=b_1
    • S0(2)=S1(2)2c0+6d0=2c1S''_0(2)=S''_1(2)\rarr 2c_0+6d_0=2c_1
    • natural boundary condition
      • S0(1)=02c0=0S_0''(1)=0\rarr 2c_0=0
      • S1(3)=02c1+6d1=0S_1''(3)=0\rarr 2c_1+6d_1=0

  • Cubic Spline의 계수 찾기

  • (xxj)=hj(x-x_j) = h_j로 정의

    • aj+1=aj+bjhj+cjhj2+djhj3a_{j+1}=a_j+b_jh_j+c_jh_j^2+d_jh_j^3
    • bj+1=bjhj+2cjhj+3djhj2b_{j+1}=b_jh_j+2c_jh_j+3d_jh_j^2
    • cj+1=cj+3djhjc_{j+1}=c_j+3d_jh_j
  • cj,cj+1c_j, c_{j+1}을 안다고 할 때

    • aj+1=aj+bjhj+hj23(2cj+cj+1)a_{j+1}=a_j+b_jh_j+\frac{h_j^2}{3}(2c_j+c_{j+1})
    • bj+1=bj+hj(cj+cj+1)b_{j+1}=b_j+h_j(c_j+c_{j+1})
    • b에 대해 정리하면 bj=1hj(aj+1aj)hj3(2cj+cj+1)b_j=\frac{1}{h_j}(a_{j+1}-a_j)-\frac{h_j}{3}(2c_j+c_{j+1})
      • bj1b_{j-1}에 대해 bj1=1hj1(ajaj1)hj13(2cj1+cj)b_{j-1}=\frac{1}{h_{j-1}}(a_{j}-a_{j-1})-\frac{h_{j-1}}{3}(2c_{j-1}+c_j)
      • 식을 정리하면 bj=bj1+hj1(cj1+cj)b_j=b_{j-1}+h_{j-1}(c_{j-1}+c_j)
  • bjbj1b_j-b_{j-1}을 대입하여 정리하면
    hj1cj1+2(hj1+hj)cj+hjcj+1=3hj(aj+1aj)3hj1(ajaj1)\rarr h_{j-1}c_{j-1}+2(h_{j-1}+h_j)c_j+h_jc_{j+1}=\frac{3}{h_j}(a_{j+1}-a_j)-\frac{3}{h_{j-1}}(a_j-a_{j-1})

    • a, h값을 알면 c를 계산 가능
    • a, c를 이용하여 b 계산 : bj=1hj(aj+1aj)hj3(2cj+cj+1)b_j=\frac{1}{h_j}(a_{j+1}-a_j)-\frac{h_j}{3}(2c_j+c_{j+1})
    • c, h를 이용하여 d 계산 : cj+1=cj+3djhjc_{j+1}=c_j+3d_jh_j
728x90
728x90
마크다운을 이용해 필기를 해보자

마크다운을 이용해 필기를 해보자

  • 연초에 마크다운의 존재를 처음 알고 쏠쏠히 써먹는 중이다.
  • 단순히 메모장으로 필기하는 것보다는 '조금' 더 상세하게 필기가 가능한데, 특히 코드 하이라이트나 VSCode extension을 이용한 이미지 붙여넣기 등의 기능 추가가 꽤 쏠쏠한 편이다.

  • 먼저 VScode를 설치한다. 다른 편집기도 많이 있긴 한데(StackEdit 등등...) 나는 이걸 쓰는게 다른 언어로 빨리 넘어가기도 좋고 해서 사용하는 편이다.
  • 설치할 익스텐션은 총 두개다 : Markdown All in One, Markdown Paste
  • 두 익스텐션까지 설치하고 나면, 이제 파일명.md로 파일 편집을 진행하면 된다.

간단한 마크다운 문법


#의 개수로 제목의 크기 조절이 가능하다(보통 2개까지가 유의미한 차이인듯)

# 1개

# 2개

# 3개

# 4개

#5개

-, +, *으로 글머리표를 쓸 수 있다.

  • 이렇게
  • 이렇게
  • 이렇게

숫자로도 순서가 있는 글머리표가 가능하다.

  1. 이렇게
  2. 이렇게
  3. 이렇게

-를 3번 쓰면 구분선이 생긴다


이렇게

`를 3번 쓰면 코드 하이라이트가 된다. 그 뒤에 언어 이름을 붙이면 해당 언어로 하이라이트가 된다.

//```c #include <stdio.h> int main(void) { printf("hello, world!"); }

꺽쇠 표시(>)를 쓰면 인용구로 사용할 수 있다.

이렇게

  • 달러 표시 사이에 있는 글들은 논문을 쓸 때 쓰는 tex 문법을 사용할 수 있다 : $$

    • 1, 12\sqrt1,\ \frac{1}{2}
  • 위에서 설치한 markdown paste는 복사한 이미지를 간단하게 붙여넣을 수 있다. ctrl+alt+v로 붙여넣으면 된다(다만 시간이 좀 걸릴 수 있다)

  • markdown all in one의 기능 중 md파일을 html로 바꾸는 기능이 있다. 이 기능을 이용하면 티스토리 글쓰기에 html 기능으로 작성한 글을 옮길 수 있다(테마에 따라 지원이 완전히 되지 않을 수 있다.)

  • 링크는 대괄호에 [표시할 이름]을, 소괄호에 (링크)를 넣는다. [ ] ( )이런 식으로(사이 공백은 붙인다.) : 이 글로 다시 돌아오는 링크

  • 이외에도 많은 문법이 있는데, 구글에 검색하면 많으나 컴퓨터로 기록할때는 이정도를 주로 쓰고 있다. 너무 악필이다 보니 컴퓨터 기록 방법을 고뇌하다 찾았는데, 생각보다 너무 유용하게 쓰이는 듯.

  • md 파일은 Github 웹사이트를 만들 때도 쓸 수 있는데, Github의 경우 티스토리보다 손이 좀 많이 가다 보니(웹사이트 구축에서 막히기 시작하니까 흥미가 훅 떨어지더라...) 그냥 티스토리에 아예 정착한 상황이다. md파일이 있으니 원할 때 그대로 옮겨갈 순 있을 것 같긴 한데, 티스토리가 섭종하지 않는 한은 그냥 이대로 갈 것 같다.

728x90
728x90
Secant Method

Secant Method

  • newton method : pn=pn1f(pn1)f(pn1)p_n=p_{n-1}-\frac{f(p_{n-1})}{f'(p_{n-1})}
  • secant method : newton method의 미분항(f')를 근사
    • f(pn)f(pn)f(pn1)pnpn1f'(p_n)\simeq\frac{f(p_n)-f(p_{n-1})}{p_n-p_{n-1}}
    • pn+1=pnf(pn)pnpn1f(pn)f(pn1)\Rarr p_{n+1}=p_n-f(p_n)\cdot\frac{p_n-p_{n-1}}{f(p_n)-f(p_{n-1})}
    • 장점 : 미분항이 없음 = 개발 시 용이
    • 단점 : 초반 point 수가 두개 (pn, pn1p_n,\ p_{n-1}), newton method보다는 느림

False Position (Ragula Falsi)

  • 기존의 Secant method는 계산에 따라 진동하면서 수렴할 위험 존재
  • 두번째 point인 p1p_1을 계산 기준점으로 삼아 uniform하게 수렴하도록 계산

Order of Convergence

  • {pn}n=0\{p_n\}^\infty_{n=0}이 p로 수렵할 때
  • limnpn+1ppnpα=λlim_{n\rarr\infty}\frac{|p_{n+1}-p|}{|p_n-p|^{\alpha}}=\lambda에서 계수 α\alpha가 수렴 형태를 결정
    • λ\lambda : error constant
    • α=1,λ<1\alpha=1, \lambda<1 : linearly convergent
      • 식이 p=0으로 수렴한다고 할 때, limnpn+1pn=0.5lim_{n\rarr\infty}\frac{|p_{n+1}|}{|p_n|}=0.5
    • α=2\alpha=2 : quadratically convergent
      • limnpn+1pn2=0.5lim_{n\rarr\infty}\frac{|p_{n+1}|}{|p_n|^2}=0.5
    • secant method의 경우 pnp_n의 계수가 1+52\frac{1+\sqrt{5}}{2}
  • bisection method / fixed-point method
    • limnpn+1pn=λlim_{n\rarr\infty}\frac{|p_{n+1}|}{|p_n|}=\lambda : λ\lambda가 작을수록 빠른 수렴 / 0.5면 bisection
    • pnλ2p0|p_n|\simeq\lambda^2|p_0|
  • newton method
    • limnpn+1pn2=λlim_{n\rarr\infty}\frac{|p_{n+1}|}{|p_n|^2}=\lambda
    • pnλ2n1p02n1|p_n|\simeq\lambda^{2^n-1}|p_0|^{2^n-1}
728x90
728x90
프로퍼티의 접근 - Setter, Getter

프로퍼티의 접근 - Setter, Getter

  • 자바의 필드 : 접근 메소드를 필요로 함
  • 코틀린의 프로퍼티 : 변수 선언 외에 접근 메소드가 별도로 있음
    • Getter/Setter : 코틀린의 프로퍼티 접근 메소드
class Person(var name: String, var age: Int) // 클래스 선언 fun main() { val user = User("Kim", 20) val name = user.name //getter에 의한 프로퍼티 반환 user.age = 25 //setter에 의한 프로퍼티 값 변경 }
  • 게터와 세터의 설정 원리 : 변수 설정 시 get(), set()이 각각 자동으로 선언됨
    • 아래 양식처럼 암묵적으로 선언되며 같은 양식대로 직접 커스텀할 수 있음
Class bar(...) { val A : Int //불변형은 getter만 선언됨 get() = field /* 프로퍼티를 get에 대입 시 무한 재귀 호출이 되기 때문에, 프로퍼티를 가리키는 변수인 field로 별도로 선언됨 */ var B : Int //가변형은 get, set 모두 선언됨 get() = field set(value) { field = value } }

지연 초기화

  • 클래스의 프로퍼티는 null일 수 없으므로 객체 생성 시 초기화가 필요한데, 객체 정보가 나중에 나타나는 경우 나중에 초기화할 방법이 필요
  • lateinit, lazy 키워드로 지연된 초기화 가능
  • lateinit
    • 클래스 간의 의존성이 있는 경우 (특정 클래스가 생성되어야 초기화할 수 있는 경우)
    • 테스트를 위해 임시로 객체를 생성해야 하는 경우
    • var형 프로퍼티만 가능
    • 초기화 전에는 프로퍼티의 getter, setter 사용이 불가
class Person { lateinit var name : String fun test() { if(~::name.isInitialized) println("not initialized") //초기화 여부 확인 else println("initialized") } } fun main() { val kildong = Person() kildong.test() //"not initialized" kildong.name() = "Kildong" //isInitialized = true kildong.test() //"initialized" } ///////////////////////////////////////////////////////// // lateinit을 이용한 클래스 생성의 지연 초기화 data class Person(var name : String, var age : Int) lateinit var person1 : Person //클래스 지연 초기화 fun main() { person1 = Person("Kildong", 30) //생성자 호출 시점에 초기화 }
  • lazy : 호출 시 by lazy로 지연 초기화
    • val에서만 사용 가능, 초기화 후값 변경 불가
    • lazy 키워드의 모드
      • by lazy(mode = SYNCHRONIZED) : 단일 스레드의 사용 보장
      • by lazy(mode = PUBLICATION) : 여러 곳에서 호출될 수 있으나 처음 초기화된 값 사용
      • by lazy(mode = NONE) : 락이 되지 않으므로 여러 스레드의 접근이 가능하나 값이 일관되지 않을 수 있음
class Lazytest { init {println("init block")} val subject by lazy { println("lazy init") "kotlin programming"//subject 접근 시 대입됨 } fun flow() { println("not init") println("subject : $subject") // 이 시점에서 subject가 초기화됨 } } fun main() { val test = Lazytest() test.flow() }
  • by를 이용한 위임
    • 람다식을 사용
    • 한 클래스가 다른 클래스에 위임
    • 위임된 클래스 멤버는 참조 없이 호출
    • <var|val|class> 이름 : 자료형 by 위임자
  • 위임을 쓰는 이유
    • 코틀린 라이브러리는 open되지 않은 클래스(상속 불가)
    • 표준 라이브러리의 복잡한 상속을 방지하나, 기능 확장이 어려움
    • 위임 사용 시 : 클래스 기능에 추가 기능을 구현 가능
interface Animal() { fun eat() {...} } class Cat = Animal() val cat = Cat() class Robot = Animal by cat //RobotCat의 멤버를 사용 가능
  • 위임의 특수 키워드
    • observable : 프로퍼티를 보다가 변경 발생 시 호출
    • vetoable : 반환값에 따른 변경 허용 및 취소
import kotlin.properties.Delegates class User { var name : String by Delegates.observable("NONAME")//observable 매개변수로 name 초기값 설정 { prop, old, new -> //프로퍼티, 기존값, 새로운 값을 매개로 받음 println("$old->$new") //이벤트 발생(name값의 변화) 시 실행 } }

정적 변수와 메서드

  • 코틀린의 클래스는 동적으로 생성
  • 동적 초기화 없이 사용 가능한 변수 = 정적 변수 : 코틀린에서는 컴패니언 객체라고 칭함
  • 사용하지 않아도 메모리에 상주하므로 자주 사용하는 객체에 대해 사용
class Person { var id : Int = 0 var name : String = "kim" companion object // 컴패니언 객체 : 객체 생성 없이 접근 가능 { var lang : String = "Kor" fun work() { println("working") } } } fun main() { println(Person.lang) //인스턴스 생성 없이 출력 가능 Person.lang = "Eng" //변경 가능 Person.work() //메소드 실행 가능 println(Person.name) //name은 companion이 아니므로 에러 }
728x90
728x90
클래스와 객체의 정의

클래스와 객체의 정의

  • 객체지향 : 절차 중심의 코드를 구조적으로 하고자 함
    • 구조적인 코드 구조를 클래스 / 객체를 이용하여 실제 세계와 비슷하게 작성
    • 객체와 그 관계를 표현하여 확장 - 재사용이 용이
  • 객체지향 용어
    • 추상화(abstraction) : 어떠한 내용을 개념화하는 작업 - 클래스의 기본 형식 구성
    • 인스턴스(Instance) : 클래스 객체 생성
    • 상속(Inheritance) : 부모 클래스의 내용을 자식 클래스로 물려받음
    • 다형성(polymorphism) : 하나의 이름으로 다양한 처리를 제공
    • 캡슐화(encapsulation) : 메소드 내용은 외부 사용자가 접근할 수 없게 함
    • 메시지 전송 : 객체 간의 데이터 교환
    • 연관 : 클래스 간의 관계
  • 언어 별 동의어(코틀린 : 그 외 언어들)
    • 클래스 : 분류, 범주
    • 프로퍼티(Property) : 속성(Attribute), 변수(Variable), 필드(Field), 데이터(Data)
    • 메서드(Method) : 함수(Function), 동작(Operation), 행동(Behavior)
    • 객체(Object) : 인스턴스(Instance)

클래스 생성자 (Constructor)

  • 클래스 생성 시 호출되는 함수
    • 객체 생성 시 필요한 값을 인자로 설정 가능
  • 주 생성자(Primary Constructor) : 클래스명과 함께 기재, 보통 constructor 키워드는 생략 가능
  • 부 생성자 (Secondary Constructor) : 클래스명 본문에 기재, 하나 이상의 부생성자를 정의 가능
class Bird { //프로퍼티 var name : String = "noname" var wing : Int //생성자 constructor(name:String, wing : Int) { this.name = name //생성자, 메소드에서 클래스 프로퍼티 참조 this.wing = wing } //메소드 fun fly() { println("Fly!") } } fun main() { val coco = Bird("coco", 2) coco.fly() }

상속(Inheritance)

  • 자식 클래스가 상위(부모) 클래스 내용을 계승
  • 상위 클래스의 프로퍼티와 메소드가 하위로 적용됨
  • open class (class명) : 클래스를 상속 가능한 상태로
    • class (클래스명) : (상위 클래스명) : 클래스 상속
    • 코틀린 클래스는 묵시적으로 Any 클래스로부터 상속됨
open class Bird(var name : String, var wing : Int) //pri. Constructor, 프로퍼티 선언한 상위 클래스 { fun fly() { println("Fly!") } } class Lark(name : String, wing : Int) : Bird() //클래스 상속 : 상위 클래스의 프로퍼티와 동일하게 Construct { fun singalong { print("sing together") } } class Parrot : Bird() { var language : String //만약 하위 클래스에 새 프로퍼티 추가 시 별도로 선언 constructor(name : String, wing : Int, language : String) : super(name, wing) //부생성자로 클래스 상속 시 super 키워드 사용 { this.language = "..." } fun speak() { println("hello?") } } fun main() { var lark = Lark("mylark", 2) var parrot = Parrot("myparrot", 2, "Eng") }

다형성(Polymorphism)

  • 같은 이름을 사용하지만 매개변수가 다른 함수
    • 하나의 이름으로 여러 기능 수행
    • static polymorphism : 컴파일 시점의 다형성, 메소드 오버로딩
    • dynamic polymorphism : 런타임 다형정, 메소드 오버라이딩
  • 오버라이딩
    • 기능을 바꾸어 재설계
    • ex. push() - 확인 / 취소 로 서로 다른 기능을 수행하게 할 수 있음
    • 클래스 상속과 같이 open으로 상위 메소드에 선언해주고, override로 상속
    • final override 사용 시 오버라이드를 선언한 클래스의 하위 클래스는 재정의 금지
  • 오버로딩
    • 같은 기능을 구현하지만 인자 수나 타입이 다름
    • ex. print("hello") (string), print(1)(int)와 같이 같은 출력이지만 받는 인자가 다름
fun add(x:Int):Int { return x+1 } fun add(x:Double) : Double { return x+1.0 //오버로딩 : 다른 type } fun add(x:Int, y:Int) : Int { return x+y //오버로딩 : 다른 인자 개수 }

super, this

  • super
    • 상위 클래스의 참조
    • super.프로퍼티, super.메소드(), super() : 프로퍼티, 메소드, 생성자 참조
  • this
    • 현재 클래스의 참조
    • this.프로퍼티, this.메소드, this() : 프로퍼티, 메소드, 생성자 참조
open class Person { //상위 클래스 constructor(firstName: String) { println("[Person] firstName: $firstName") } constructor(firstName: String, age: Int) { //생성자 오버로딩 println("[Person] firstName: $firstName, $age") } } class Developer: Person { //Person 클래스 상속 constructor(firstName: String): this(firstName, 10) { // Developer 클래스의 아래 constructor 접근 (age default로 10 대입) println("[Developer] $firstName") } constructor(firstName: String, age: Int): super(firstName, age) { // Developer Class의 상위 클래스인 Person Class의 생성자 접근 println("[Developer] $firstName, $age") } }
  • 외부 클래스 호출(@)
    • 클래스 내부의 클래스(inner class)에서 상위 클래스 호출 시 super@클래스명으로 호출한다.
  • 앵글브라켓(<>)
    • 클래스와 인터페이스 중복 사용 시 사용할 상위 클래스를 지정 가능
open class A { open fun f() = println("A class f") fun a() = println("A class a") } interface B { fun f() = println("B interface f") fun b() = println("B interface b") } class C : A(), B { override fun f() = println("C class f") fun testing() { f() //C클래스의 f b() //B 인터페이스의b super<A>.f() //A클래스의 f super<B>.f() //B클래스의 f } }

가시성 지시자와 캡슐화

  • 클래스를 작성할 때 클래스 외부로부터 접근을 차단하는 속성이나 기능
  • 가시성 지시자(visibility modifier)
    • private : 클래스 내부에서만 접근 가능
    • public : 접근 가능(기본값)
    • protected : 상속된 클래스만 접근 가능
    • internal : 같은 모듈 내에서만 접근 가능
    • 변수명, 함수명, 클래스명, 지시자 등에 붙을 수 있음
728x90
728x90
람다식과 고차함수 요약

강의 링크 : https://www.edwith.org/boostcourse-mo-kotlin-basic1/joinLectures/28611

람다식과 고차함수 요약

  • 람다식 : {인자 -> 본문}
val sum : (Int, Int) -> Int = {x, y -> x+y} val mul = {x:Int, y:Int -> x * y} val add : (Int) -> Int = {it + 1} //it은 전달받은 인자를 의미 (함수 인자가 하나인 경우)
  • 고차 함수 : 리턴값이나 인자가 함수인 함수
fun high(name : String, body : (Int)->Int) : Int { prinln("name : $name") val x=0 return body(x) } //함수 호출 val res1 = high("TxT", {x->inc(x+3)}) //인자로 전달되는함수 인자가 하나인 경우 : it으로 대체 가능 val res2 = high("TxT") {inc(it+3)} //매개변수가 없을 때 함수 이름만 사용 val res3 = high("TxT", ::inc) //inc는 람다식으로 변환됨 // 매개변수가 하나인 경우 + 람다식 전달 val res4 = high("TxT") {it+3}

클로저

  • 람다식 함수에서 외부 변수에 접근할 수 있는 방법
  • 외부 변수를 capture하여 사용
fun main() { val calc = Calc() var result = 0 // 외부의 변수 calc.addNum(2,3) { x, y -> result = x + y } // 클로저 println(result) // 값을 유지하여 5가 출력 } class Calc { fun addNum(a: Int, b: Int, add: (Int, Int) -> Unit) { // 람다식 add에는 반환값이 없음 add(a, b) } }

코틀린 표준 라이브러리

  • 코틀린 표준 함수는 확장 함수 형태의 람다식으로 제공
  • let() : 객체를 인자로 넘기고 결과값 반환
//main문 내 val score : Int?=32 // 기존 null검사 fun chkScore() { if (score != null) println("Score : $Score") } //let을 이용한 null검사 - null이면 {...}이 실행되지 않음 fun letChkScore() { score?.let{println("Score:$it)} }
  • also() : let은 결과값 반환, also는 함수에 전달한 객체를 반환
    • 함수 블록 {...}의 마지막 문장을 let은 결과로 반환
    • also를 사용 시 마지막 문장을 반환하지 않음 (=대입이 안됨)
var m=1 m = m.also{it+3} //m은 1 - 연산한 결과가 m에 대입되지 않음
  • apply(): also와 같이 객체를 전달하고 반환받음
    • also와 달리 확장 함수로 처리되므로 클래스 인자 접근 시 it을 사용하지 않아도 됨
val person = Person("", 0) //apply val result = person.apply { name = "James" age = 56 } //also val result = person.also { it.name = "James" it.age = 56 }
  • run() : 익명 함수 / 객체 호출 두가지로 활용
    • block 내용 수행 후 결과값을 반환
    • 조건부 메소드 사용 가능
    • apply와 다르게 객체에 접근하면서 함수 블록{...}의 마지막 결과가 실행됨
run { if (firstTimeView) introView else normalView }.show()
  • with() : 전달받은 객체를 처리
    • safe call(?.)이 없으므로 let과 함께 쓰임
supportActionBar?.let { with(it) { setDisplayHomeAsUpEnabled(true) setHomeAsUpIndicator(R.drawable.ic_clear_white) } }
  • use() : 객체 사용 후 호출한 객체를 닫아줌(close())
    • 파일을 사용할 때 유용
private fun readFirstLine() : String { BufferedReader(FileReader("text.txt")).use{ return it.readline() } }
728x90
728x90
조건문을 통한 분기 (1)

강의 링크 : https://www.edwith.org/boostcourse-mo-kotlin-basic1/joinLectures/28611

조건문을 통한 분기 (1)

  • C언어의 조건식과 유사
if(...) { ... } else if (...) { ... } else { ... } val bar = if(...) a else b //1줄로 축약 가능 //if문을 이용한 대입 val a = 1 val b = 2 val bar = if(...) { println("a") a } else { println("b") b }
  • in 연산자 : 범위 내에 값이 있는지 확인
if (score >= 80 && score <= 89>) //score이 80 ~ 89 내인지? if (score in 80..89) { ... } // 위와 동일한 동작

조건문을 통한 분기 (2)

  • When문 : Switch - Case문의 간략화
when(x) { /*(일치하는 값 or 표현식) -> 수행할 명령문*/ 0, 1 -> printf("x is 0 or 1") returnvalue(x) -> print("return is correct") // 함수 리턴값과 비교 is Int -> println("x is int") /*(일치하는 범위) -> 수행할 명령문*/ in 1..10 -> println("x is in 1 ~ 10") !in 10..20 - > println("x is not in 10 ~ 20") ... /*else -> 수행할 명령문*/ else -> println("??") }
  • 인자가 없는 경우 - 다양한 조건식 구성 가능
var scroe = readline()!!.toDouble() var grade : Char = 'F' when { score >= 90.0 -> grade = 'A' score in 80.0..89.9 -> grade = 'B' score in 70.0..79.9 -> grade = 'C' else -> grade = 'F' } ...

반복문

  • for문
for(x in 1..5) // (요소 변수 in (컬렉션 or 범위)) { ... }
  • 다양한 반복법
//감소 for (i in 5 downto 1) //5,4,3,2,1 //단계별 증가 for (i in 1..5 step 2) //1, 3, 5 //혼합 for (i in 5 downto 1 step 2) //5, 3, 1
  • while문 : C의 while / do-while과 동일하게 동작한다.
while(...) { ... } //조건을 만족하는 동안 계속 동작 do { ... }while(...) //조건 검사가 밑에서 동작하므로 처음 1회는 무조건 동작

흐름의 중단과 반환 (1)

  • 흐름 제어
    • return : 함수의 결과를 반환
      • 반환값이 없는 경우 return 혹은 return Unit
      • 함수 마지막에는 Unit을 생략해도 return Unit이 동작함
    • break : 반복문을 끝냄
    • continue : 반복문 내용을 생략하고 조건으로 넘어감
  • 예외 처리
    • try {...} catch {...} : 예외 발생시 catch 내용 수행
    • try {...} catch {...} finally {...} : 예외가 발생해도 finally 내용은 수행

예외 처리

  • 실행 도중에 비정상적으로 프로그램 종료 시
    • OS 문제 (System Call Fault 등)
    • 입력값 문제 (int형에 문자열 입력 등)
    • 연선 문제 (divide by zero 등)
    • 메모리 할당 실패
    • HW 문제(전원 문제, 기억 장치 문제 등)
try { //예외처리 가능성이 있는 문장 } catch(e:classname) //e:예외처리 클래스 이름 { //예외처리 문장 } finally { //try-catch와 무관하게 실행할 문장 }
  • 사용자에 의한 예외 발생
    • throw Exception(message : String)을 이용
if(/* error */) { throw Exception("Error!") }
728x90

+ Recent posts