Kotlin에는 기본 Data types이 있습니다.

Category Basic Types more...
Integers Byte, Short, Int, Long 기본 정수 숫자(음의 정수,0, 양의 정수 모두 포함)
Types이 나뉘는 기준은 숫자의 크기
Unsigned integers UByte, UShort, UInt, ULong 0을 포함한 양의 정수
Types이 나뉘는 기준은 숫자의 크기
Floating-point numbers Float, Double 음의 실수, 0, 양의 실수
Types이 나뉘는 기준은 숫자의 크기
Booleans Boolean true, false, null 
Characters Char 문자 하나
Strings String 문자열

Integers types

Byte가 기본 값입니다. 1Byte는 8bits입니다.

컴퓨터는 우리가 쓰는 말과 다른 언어로만 이야기합니다. 

그 언어는 0과 1만 알아듣습니다. 8개의 칸에 들어갈 수 있는 것은 0 또는 1입니다.

0과 1로 이루어진 숫자 체계를 이진수라고 합니다.

Bit가 0일때는 숫자 할당이 안되며 1인경우에는 아래와 같이 2에 지수로 표현됩니다.

1BYTE

00000000은 10진수의 0입니다.

00000001은 10진수의 1(20)입니다.

00000010은 10진수의 2(21)입니다.

00000011은 10진수의 3(20 + 21)입니다.

00000100은 10진수의 4(22)입니다.

 

이런 식으로 숫자를 표현하며 최대한으로 표현할 수 있는 숫자는 0 ~ 255까지 256개의 숫자입니다.

그렇다면 실제로 그럴까요?

답은 아닙니다. Integer types은 음의 정수와 양의 정수 모두를 포함합니다.

따라서 -128 ~ 127까지의 256개의 숫자를 표현합니다.

부호를 인식하는 방식이나 표시하는 방식이 시스템이나 언어에 따라 다릅니다.

그렇지만 이론적으로 아래와 같운 설명이 가능합니다.

맨 왼쪽의 bit는 부호를 결정하는 bit입니다.

0이면 양의 정수

1이면 음의 정수

그렇다면 10000000은 어떤수일까요? -0일까요?

아닙니다. 10000000은 -128입니다.

11111111은 계산상으로는 더 커보이지만 맨 왼쪽 bit가 -를 나타내고 그 다음 자리부터 계산하게 되면 127 즉 - 127이 됩니다.

00000001은 양의 정수 1이고, 10000001은 음의 정수 -1입니다.

 

Integer에는 Byte, Short, Int, Long이 있습니다. 차이는 bits 사이즈입니다.

Byte 마찬가지로 맨 오른쪽 bit가 부호비트이고 나머지는 이진수 숫자를 나타내는 bit들입니다.

Type Bits Min value Max value
Byte 8 -128(-27) 127(27-1)
Short 16 -32,768(-215) 32,767(215-1)
Int 32 -2,146,483,648(-231) 2,147,483,647(231-1)
Long 64 -9,223,374,036,854,775,808(-263) 9,223,374,036,854,775,807(263-1)

 

명시적으로 Data type을 선언하지 않고 값을 할당하는 경우 Kotlin에서는 기본적으로 Int로 처리합니다.

즉, 4Bytes(32bits)의 메모리 공간을 사용합니다.

큰수를 다루지 않는 경우는 그 크기에 따라 Byte 또는 Short로 명시적 선언을 해주는 것도 좋습니다.

 

여기서 만약 명시적으로 Data type을 설정하지 않고 Int에 할당할 수 있는 값보다 더 큰 수를 할당한다면 어떻게 될까요?

자동적으로 Long으로 Data type이 선언됩니다.

Integer Types

 

Unsigned integer types

Kotlin에서는 부호가 없는 즉, 0과 양수의 정수 Data types도 제공합니다.

Type Bits Min value Max value
UByte 8 0 255(28-1)
UShort 16 0 65,535(216-1)
UInt 32 0 4,294,967,295(232-1)
ULong 64 0 18,446,744,073,709,551,615(264-1)

 

unsigned integer types

 

Floating-point types

실수의 경우, 부동 소수점 Float과 Double을 제공합니다.

앞에 알아보았던 정수의 경우는 소수점 이하자리가 없기 때문에 간단합니다. 2진수에 대해서만 이해하면 바로 이해가 됩니다.

소수점을 포함한 실수는 좀 복잡합니다. 대략 적으로 이해하기 위해 먼저 간단히 살펴보겠습니다.

Floating point types은 Sign(부호), Exponent(지수부), Mantissa(가수, Fraction이라고도 함)로 구성되어있습니다.

 

10진수 → 2진수로 변환

① 10진수를 나머지가 1혹은 0이될때까지 2로 나눈다

② 각 나눔 단계에서 나머지를 취한다.

무슨 말인지 직접 보면 쉽게 이해가 갑니다.

10진수를 2진수로 변환

 

10진수 소수점 이하 → 2진수로 변환

① 10진수의 c점 이하 숫자에 2을 곱하여 소수점 윗 자리를 취한다.

② 계산의 결과가 0이나 1이 나올때까지 반복합니다.

10진수 소수점 이하를 2진수로 변환

여기서 잠깐 이진수 계산에 따른 컴퓨팅의 한계를 살펴보겠습니다.

10진수 0.3은 2진수로 어떻게 표현될까요.

0.3 X 2 = 0.6  - 0

0.6 X 2 = 1.2  - 1

0.2 X 2 = 0.4 - 0

0.4 X 2 = 0.8 - 0

0.8 X 2 = 1.6 -  1

0.6 X 2 = 1.2 - 1

0.2 X 2 = 0.4 - 0

0.4 X 2 = 0.8 - 0

0.8 X 2 = 1.6 - 1

0.6 X 2 = 1.2 - 1

무엇인가 심상치 않지요? 계산이 끝나지 않고 계속 반복됩니다.

10진수 0.3을 2진수로 변환하게 되면 0.01001100110011001.... 이렇게 1001을 무한반복하게 됩니다.

즉 정확한 10진수 0.3이 아니라 그 근사치까지만 표현이 가능합니다.

이런 이유로 소수점을 포함한 계산은 컴퓨터에서 기본적으로 오류를 범할 수 있는 가능성을 내포하고 있습니다.

 

그렇다면 Floating-points types인 Float와 Double은 어떨까요? 

답은 "마찬가지다." 입니다. 여전히 소수점 이하자리에 대한 오류를 포함하고 있습니다.

따라서 Float와 Double을 통해 계산을 할 경우에는 조심해야겠지요. 지금은 계산 오류가 있을 수 있다 정도만 알겠습니다.

 

Float은 4Bytes 즉, 32bits의 크기를 갖습니다.

  • Sign(부호) : 맨 왼쪽 1bit. 0이면 양수, 1이면 음수
  • Exponent(지수) : Sign bit 이후 8bits, 지수를 나타냅니다.
  • Mantissa(가수) : 23bits, 가수 또는 유효 숫자를 나타냅니다.

도대체 무슨 말일까요? Kotlin만이 아니라 대부분의 언어는 숫자에 따른 규격을 따릅니다.

실수에 대해서는 IEEE Standard for Floating Point Arithmetic(IEEE 754) 규경을 따릅니다.

 

25.625를 Float으로 표현해보겠습니다.

우선 Sign은 양수 이므로 0입니다.

25.625를 이진수로 표현하면 11001.101(2)입니다.

소수점을 맨앞에 1이후로 옮겨보겠습니다. 

1.1001101(2)

소수점이 앞으로 4bit 이동 했습니다.

11001.101(2) = 1.1001101 x 24

로 표현할 수 있으며, 이러한 표현을 정규화 표현 방식이라고 부릅니다.

정규화 표현식의 1.1001101에서 소수점 아래자리 즉 1001101으로 Mantissa로 사용합니다.

 

이제 Exponent(지수)를 채워보겠습니다.
지수가 4입니다. Exponent 8bits의 bias(bias = 2n-1, n은 Exponent bit수)를 더해줍니다. 

4+127 = 131을 이진수로 변환하면 10000011(2)입니다. 가수부에 채워주게 되면 아래와 같이 완성됩니다.

01000001110011010000000000000000이 Float로 표현된 25.625입니다.

검산을 해보려면 IEEE-754 Floating Point Converter에서 확인할 수 있습니다.

 

Double은 8Bytes 즉, 64bits의 크기를 갖습니다.

  • Sign(부호) : 맨 왼쪽 1bit. 0이면 양수, 1이면 음수
  • Exponent(지수) : Sign bit 이후 11bits, 지수를 나타냅니다.
  • Mantissa(가수) : 53bits, 가수 또는 유효 숫자를 나타냅니다.

변환 방식은 Float와 유사합니다.

 

Double과 Float에 대해서 정리해보았습니다.

Type Bits Sign bit Exponent bits Mantissa bits
Float 32 1 8 24
Double 64 1 11 53

 

Kotlin에서 Double과 Float는 정수부와 소수점 그리고 소수점 이하 숫자로 이루어 집니다.

val doubleNmuber = 1.0 //Double
// val one: Double = 1 // Double로 선언한 변수에 Int를 할당하여 Error가 발생

val floatNumber = 1.0f // 숫자뒤에 f 혹은 F를 붙여 float으로 할당
// val floatNumber2: Float = 1.0  // Float으로 선언한 변수에 Double을 할당하여 Error 발생

 

 

Kotlin에서는 몇가지 수의 표현 방식이 있습니다.

  • Decimal : 123
  • Long : 123L
  • Binaries(2진수) : 0b00001011
  • Hexadecimals(16진수): 0x0F
  • Octaldeciamls(8진수): Kotlin에서 지원하지 않음
  • Double : 125.123, 1.25123e10
  • Float : 124.123f, 124,123F
  • Unsigned : 10u, 10U
  • Unsigned Long : 1000uL, 1000UL

Kotlin에서는 코드의 가독성을 위해 숫자 자리수를 표현할 수 있도록 제공해줍니다.

우리가 현실세계에서 사용할때는 보통 , 를 사용합니다. 10,000이런 식으로요. 

Kotlin에서는 _ 를 사용합니다.

val thousand = 1_000
val tenThousand = 10_000
val million = 1000_000
val longNumber = 123_456_789_000_000L
val hexBytes = 0xFF_EF_CA
val bytes = 0b10101001_01110100_11110000

 

Kotlin에서 한가지 재미있는 현상을 볼까요? 

 

Kotlin에는 java에는 없는 === 비교 연산자가 있스니다. 객체(레퍼런스)를 비교하는 연산자 입니다. 나중에 자세히 다뤄보겠습니다.

우선 JVM의 메모리 관리 특성상 Byte의 범위안의 숫자(-128~127)로 할당된 숫자는 nullable 변수에 할당할경우 레퍼런스로 참조하게됩니다.즉, b와 c 모두가 나는 a의 값을 참조해라고 하는거요. 그래서 값도 같고, 객체를 비교했을때도 같습니다.

그러나 Byte 범위 안의 숫자가 아닌 경우, 각자 메모리의 값을 할당하고 값을 저장합니다. 그렇게 되면 서로 다른 객체로 메모리에 저장되겠지요. 지금은 좀 헷갈리지만 때가되면 자세히 다루어보겠습니다. 

 

Kotlin에서는 모든 숫자 types들 간의 명시적인 변환을 지원합니다.

  • toByte() : Byte
  • toShort() : Short
  • toInt() : Int
  • toLong() : Long
  • toFloat() : Float
  • toDouble() : Double

참고로 명시적으로 변환하지 않아도 자동으로 변환되는 경우도 있스빈다. 

// Long으로 명시된 1에 정수 3을 더한 longNumber는 Long type 
val longNumber = 1L + 3

 

우리가 잘 알고 있는 10진수, 앞에서 살펴본 2진수, 그외에도 16진수가 우리에게 친근합니다.

컴퓨터는 2진수를 기반으로 사람과 소통합니다. 컴파일러는 우리가 만든 코드를 2진수 기계어로 변환하여 컴퓨터가 이해하도록 합니다.

물론 코드를 구현하다보면 16진수를 사용하여 수를 표현하기도 합니다.

예를 들어 색을 표현하기 위해 RGB code를 사용합니다.

RGB는 Red, Green, Blue를 의미하며, 빛의 3원색(trichromat of ligth)라고 합니다.

우리가 흔히 말하는 3원색과는 조금 다르죠? 흔히들 3원색하면 빨노파라고 이야기들 합니다. 

이야기가 다른 곳으로 빠지는 듯 하지만 잠시 정확한 지식을 위해 확인해보면,

Magneta(자홍), Yellow(노랑), Cyan(청록)라는 색의 3원색(trichromat of color)가 있습니다.

빛의 3원색은 태양, 전등, 모니터, 촛불 등 광원에서 나오는 색

색의 3원색은 우리가 사물을 바라보았을때 빛을 반사해서 받아들이는(보이는) 색을 말합니다.

초록색 나뭇잎은 초록색 파장의 색만 반사하고 나머지 파장의 색은 흡수하기 때문에 파랗게 보입니다. 이런 것을 우리는 색이라고 하지요.

색의 3원색이 빨노파가 아닌가요? 라고 의문이 듭니다.

3원색은 3가지 색을 조합하면 어떤 색이든 만들 수 있기 때문에 3원색이라고 합니다.

물감을 섞어서 여러가지 색을 만들때 3원색은 정확히 자홍, 노랑, 청록이 맞습니다. 하지만, 빨노파의 기억이 좀 더 정겹기는 합니다.

R을 0~255, G 0~255, B 0~255로 표현하여 색의 조합을 표현합니다.

RGB를 모두 섞으면 흰색 빛이 됩니다. 모니터에서 흰색 화면이 보인다면 그건 R 255, G 255, B 255 입니다.

컴퓨터는 2진수를 이해하기에 흰색을 이진수로 표현하면 R 11111111, G 11111111, B 11111111입니다. 

즉 111111111111111111111111(2)입니다. 이런 경우 코드에서는 좀더 명시적인 16진수를 사용합니다. 

Kotlin에서는 16진수를 0x를 붙여 표현합니다. 그럼 희색은 0xFFFFFF가 되겠네요.

 

'DEVELOPMENT > Kotlin' 카테고리의 다른 글

6. Kotlin, Basic Data Types - Characters  (0) 2024.02.25
5. Kotlin, Basic Data Types - Boolean  (0) 2024.02.25
3. Kotlin, Data Types - Basics  (0) 2024.02.22
2. Kotlin, Variables  (0) 2024.02.22
1. Kotlin "Hello, world!!!"  (0) 2024.02.22

Kotlin의 모든 variables(변수) 혹은 data structure(데이터 구조)는 data type을 갖습니다.

data type을 선언해주어야 compiler(컴파일러)에서 이해하고 해석할 수 있습니다.

 

값을 변경할 수 있는 변수를 mutable variables이라고 합니다. 즉, var로 선언한 변수입니다.

(mutable은 영어단어로 '변할 수 있는, 잘 변하는' 이라는 뜻을 가지고 있습니다.)

 

반대로 한번 값을 할당하면 변경할 수 없는 변수를 immutable variables라고 합니다.

 

그럼 변수에 값을 할당함에 따라 Data type이 설정되는지 확인해 보겠습니다.

a 변수에 정수 1을 할당하였고, 정수 b에는 "문자"를 할당했습니다. 명시적으로 Data Type을 선언하지 않았지만 할당된 값의 Data type에 따라 변수의 Data type이 결정되었습니다.  

 

위 결과에서 정수는 int라고 출력이 되고 문자열은 class java.lang.String이라고 출력되었을까요?

엄밀히 말하면 둘다 class입니다. 차이점이 있다면, JVM에는 int와 integer가 있습니다.

int는 Primitive 자료형이라고 합니다. 즉, 데이터를 가지는 원시적 자료형을 뜻합니다.

그렇지만 Kotlin에서는 primitive 자료형인 Int에 많은 기능을 부여하여 Integer를 사용하지 않아도 되도록 하였습니다.

오히려 Integer를 사용하면 경우에 따라 예상치 못한 오류가 발생할 수 있습니다.

실제로 위 코드에 Integer로 선언한 부분 왼쪽에 !표가 있습니다.

마우스 커서를 이동해 올려보면 경고 문구가 나옵니다.

기억하세요. Kotlin에서는 Int를 사용합니다.

Kotlin에서 Int가 아닌 Integer로 판단되어야하는 경우 알아서 Integer로 Data type을 설정해줍니다.

코딩을 할때는 Int로 선언하고 사용하면 문제가 발생하지 않습니다.

예를 들어, Int는 primitive 자료형으로 null 값을 할당 할 수 없습니다.

 

그렇지만 Kotlin에서는 ? operator를 제공합니다. 즉 ?를 사용해 null이 될 수 있다고 알려줍니다.

? Operator

실행 결과 null을 할당했을때 a의 Data type도 null 입니다.

a 값을 출력한 결과가 null 인것은 알겠는데, a.javaClass 출력값이 왜 null 일까요?

a?.javaClass는 ? operator에 따라 a가 null이 아니면 a.javaClass를 a가 null 이면 null을 반환합니다.

 

a에 1을 할당했을때  Data type이 Int가 아니라 Integer입니다. 

왜 그럴까요? Kotlin에서 null 할당이 가능한 Integer class로 알아서 제공해준 결과입니다.

그렇지만, 개발자 입장에서는 Int와 Integer를 구분해서 사용할 필요가 없습니다.

Kotlin이 다른 언어에 비해서 사용하기 편한 이유 중에 하나입니다.

(이 외에도 많겠지요... ? operator의 존재도 마찬가지로 Kotlin이 사용하기 편한 이유가 되겠네요.)

'DEVELOPMENT > Kotlin' 카테고리의 다른 글

6. Kotlin, Basic Data Types - Characters  (0) 2024.02.25
5. Kotlin, Basic Data Types - Boolean  (0) 2024.02.25
4. Kotlin, Basic Data Types - Numbers  (0) 2024.02.23
2. Kotlin, Variables  (0) 2024.02.22
1. Kotlin "Hello, world!!!"  (0) 2024.02.22

영어로 'Variables', 우리말로 '변수'라고 합니다.

변수는 데이터를 저장하는 곳입니다.

 

모든 프로그램 언어에는 Variables(변수)가 있습니다. 

Kotlin에서는 funtion(함수)를 선언할때 fun을 앞에 붙이듯이  

변수를 선언할때는 val 또는 var을 앞에 붙입니다.

 

val은 한번 값을 저장하면 변경할 수 없는 변수 선언입니다.

var은 몇번이고 값을 변경하여 저장할 수 있습니다.

 

변수에 값을 설정하는 방법은 operator = 을 사용하면 간단히 해결됩니다.

 

Kotlin Play에서 val로 선언한 변수의 값을 변경해볼까요.

val로 선언한 변수에 값을 변경하려고 시도

"Val 변수는 값을 바꿀수 없어요." 라고 알려줍니다.

 

그럼 var로 선언한 변수는 어떨까요?

var로 선언한 변수에 값을 변경하려고 시도

문제없이 잘 바뀌어서 출력됩니다.

 

Kotlin 공식 문서에서는 변수에 할당할 내용을 변경하지 않으면 val을 사용하라고 권장합니다.

변경하면서 사용해야하는 경우, 그러니까 필요한 경우에만 var을 사용하여 변수를 선언하라고 합니다.

 

Kotlin 변수 선언에 대해서 알아보았습니다. 

변수를 선언하거나 사용하는 것에는 다양한 방법이 있습니다.

우선은 Kotlin의 val과 var을 이해하는 것으로 마무리하겠습니다.

 

'DEVELOPMENT > Kotlin' 카테고리의 다른 글

6. Kotlin, Basic Data Types - Characters  (0) 2024.02.25
5. Kotlin, Basic Data Types - Boolean  (0) 2024.02.25
4. Kotlin, Basic Data Types - Numbers  (0) 2024.02.23
3. Kotlin, Data Types - Basics  (0) 2024.02.22
1. Kotlin "Hello, world!!!"  (0) 2024.02.22

+ Recent posts