Integer Types
Type | Size(bits) | Min value | Max value |
Byte | 8 | -128 | 127 |
Short | 16 | -32768 | 32767 |
Int | 32 | -2,147,483,648 (-2^31) | 2,147,483,647 (2^31 - 1) |
Long | 64 | -9,223,372,036,854,775,808 (-2^63) | 9,223,372,036,854,775,807 (2^63 - 1) |
•
명시적인 타입 지정 없이 변수를 초기화하면 가장 작은 범위의 타입을 자동으로 추론
•
L 태그를 통해 Long 타입을 명시
val one = 1 // Int
val threeBillion = 3000000000 // Long
val oneLong = 1L // Long
val oneByte: Byte = 1
Kotlin
복사
Unsigned Integer Types
Type | Size (bits) | Min value | Max value |
UByte | 8 | 0 | 255 |
UShort | 16 | 0 | 65,535 |
UInt | 32 | 0 | 4,294,967,295 (2^32 - 1) |
ULong | 64 | 0 | 18,446,744,073,709,551,615 (2^64 - 1) |
•
Unsigned numbers 타입들은 하나의 필드를 갖는 inline class로 구현
•
u 또는 U 태그를 통해 Unsigned numbers를 나타냄
•
uL 또는 UL 태그를 통해 ULong을 나타냄
•
Unsigned number array가 존재하며 박싱 오버헤드가 없다.
◦
UByteArray, UShortArray, UIntArray, ULongArray
Floating-point Types
Type | Size (bits) | Significant bits | Exponent bits | Decimal digits |
Float | 32 | 24 | 8 | 6-7 |
Double | 64 | 53 | 11 | 15-16 |
•
소수점이 있는 숫자는 기본적으로 Double로 추론
•
f 또는 F 태그를 통해 소수점이 있는 숫자를 Float로 추론
•
소수점 자릿수를 넘으면 해당 자릿수까지 반올림
숫자의 리터럴 상수
Literal constants | Value |
Decimal | 123 |
Hexadecimals | 0x0F |
Binaries | 0b00001011 |
•
언더스코어를 이용하여 가독성 있는 숫자 상수를 사용 가능
val oneMillion = 1_000_000
val creditCardNumber = 1234_5678_9012_3456L
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010
Kotlin
복사
JVM에서의 숫자 표현
•
JVM에서 숫자는 기본 유형으로 저장된다.
•
nullable이거나 generic한 경우는 Wrapper Class로 저장된다.
•
JVM의 캐싱 범위(기본 -128~127)에 따라 같은 주소값을 사용한다.
//주소값 비교
val a: Int = 100
val boxedA: Int? = a
val anotherBoxedA: Int? = a
val b: Int = 10000
val boxedB: Int? = b
val anotherBoxedB: Int? = b
println(boxedA === anotherBoxedA) // true
println(boxedB === anotherBoxedB) // false
//동등성 비교
val b: Int = 10000
println(b == b) // Prints 'true'
val boxedB: Int? = b
val anotherBoxedB: Int? = b
println(boxedB == anotherBoxedB) // Prints 'true'
Kotlin
복사
명시적 숫자 변환
•
작은 유형은 큰 유형의 하위 유형이 아니다.
•
작은 유형은 큰 유형으로 암묵적으로 변환되지 않기 때문에 명시적 변환이 필요하다.
•
유형이 컨텍스트에서 유추된다면 명시적 변환이 필요하지 않다.
// Hypothetical code, does not actually compile:
val a: Int? = 1 // A boxed Int (java.lang.Integer)
val b: Long? = a // Implicit conversion yields a boxed Long (java.lang.Long)
print(b == a) // Surprise! This prints "false" as Long's equals() checks whether the other is Long as well
Kotlin
복사
val b: Byte = 1 // OK, literals are checked statically
// val i: Int = b // ERROR
val i1: Int = b.toInt()
Kotlin
복사
숫자에 대한 작업
•
표준 산술 연산 세트
◦
+, -, *, /, %
•
정수의 나눗셈
◦
정수를 나누면 모든 소수 부분을 삭제하고 항상 정수를 반환한다.
◦
부동 소수점으로 반환하려면 인수 중 하나를 명시적으로 부동 소수점 형식으로 변환해야한다.
val x = 5 / 2
//println(x == 2.5) // ERROR: Operator '==' cannot be applied to 'Int' and 'Double'
println(x == 2)
val x = 5L / 2
println(x == 2L)
val x = 5 / 2.toDouble()
println(x == 2.5)
Kotlin
복사
•
비트 연산
◦
Int, Long에만 적용된다.
val x = (1 shl 2) and 0x000FF000
Kotlin
복사
◦
shl(bits) - 부호 있는 왼쪽 시프트 (ex. 1 shl 2 는 0001 → 0100)
◦
shr(bits) - 부호 있는 오른쪽 시프트 (ex. 4shr 1 은 0100 → 0010)
◦
ushr(bits) - 부호 없는 오른쪽 시프트 (ex. 4 ushr 1 은 0100 → 0010)
◦
and(bits) - 비트 AND (ex. 5 and 3 은 0101 and 0011 → 0001)
◦
or(bits) - 비트 OR (ex. 5 or 3 은 0101 or 0011 → 0111)
◦
xor(bits) - 비트 XOR (ex. 5 xor 3 은 0101 xor 0011 → 0110)
◦
inv() - 비트 반전 (ex. 5.inv() 는 0101 → 1010)
•
부동 소수점 숫자 비교
◦
NaN은 자기 자신과 같다고 간주된다.
◦
NaN은 POSITIVE_INFINITY를 포함한 다른 어떤 요소보다 크다고 간주된다.
◦
-0.0은 0.0보다 작다고 간주된다.
// 피연산자가 정적으로 부동 소수점 숫자로 타입이 지정된 경우
println(Double.NaN == Double.NaN) // false
// 피연산자가 정적으로 부동 소수점 숫자로 타입이 지정되지 않은 경우
// NaN은 자기 자신과 같다고 간주됩니다.
println(listOf(Double.NaN) == listOf(Double.NaN)) // true
// 피연산자가 정적으로 부동 소수점 숫자로 타입이 지정된 경우
println(0.0 == -0.0) // true
// 피연산자가 정적으로 부동 소수점 숫자로 타입이 지정되지 않은 경우
// -0.0은 0.0보다 작다고 간주됩니다.
println(listOf(0.0) == listOf(-0.0)) // false
println(listOf(Double.NaN, Double.POSITIVE_INFINITY, 0.0, -0.0).sorted())
// [-0.0, 0.0, Infinity, NaN]
Kotlin
복사