Image
Kotlin/기타

[Kotlin] UByte, UShort, UInt, ULong 사용해 부호 없는(Unsigned) 정수 다루기

코틀린의 양의 정수 타입

일반적인 다른 언어들과 같이 코틀린에서도 부호 없는 정수(0 보다 크거나 같은 정수)형 데이터 타입을 다루기 위한 다양한 타입들이 코틀린 1.5버전부터 지원되기 시작했다. 글의 제목이 있는 UByte, UShort, UInt, ULong이 그 타입들이다.

 

변수를 각 타입으로 만드는 방법은 어렵지 않다. 우리가 Float을 선언할 때 접미어로 f를 붙이는 것처럼 접미어로 U를 붙여주면 된다.

fun main() {
  val uByte: UByte = 100U // U를 붙여주어야 한다.
  val uShort: UShort = 10_000U // U를 붙여주어야 한다.
  val uInt: UInt = 1_000_000U // U를 붙여주어야 한다.
  val uLong: ULong = 100_000_000UL // U를 붙여주어야 한다.

  println("uByte: $uByte")
  println("uShort: $uShort")
  println("uInt: $uInt")
  println("uLong: $uLong")
}

 

위 코드를 실행해보면, 일반 숫자와 같이 출력되는 것을 확인할 수 있다. 

그림1. Unsigned Values

 

각 타입의 범위

기존에 Byte가 8비트, Short가 16비트, Int가 32비트, Long이 64비트를 할당 받던 것과 같이 UByte, UShort, UInt, ULong 각각은 순서대로 8비트, 16비트, 32비트, 64비트를 할당 받는다. 최소 값은 0이며 따라서 256개의 값을 가질 수 있는 UByte는 0~255 범위의 값을, 65356개의 값을 가질 수 있는 UShort는 0~65,535 범위의 값을, UInt는 0~4,294,967,295 범위의 값을, ULong은 0~18,446,744,073,709,551,615 범위의 값을 가진다. 이를 표로 나타내면 다음과 같다.

 

타입 이름 할당 비트 수 범위
UByte 8 0~255
UShort 16 0~65,535
UInt 32 0~4,294,967,295 
ULong 64 0~18,446,744,073,709,551,615 

 

 

Unsigned 타입은 어떻게 구현되는가?

Unsigned 타입은 내부적으로 Signed Type의 값을 래핑하는 형태로 구현된다. 다음은 그 예시인 UByte이다. constructor 내부에서 Byte를 감싸고 있는 것을 볼 수 있다.

public value class UByte @kotlin.internal.IntrinsicConstEvaluation @PublishedApi internal constructor(@PublishedApi internal val data: Byte) : Comparable<UByte>

 

그렇다면 어떻게 음을 표현하는 값을 양의 값으로 바꾸는 것일까? 바로 And 연산을 통해 그렇게 한다. Unsigned Byte 내부에 있는 진짜 데이터인 Byte는 데이터를 Unsigned 값으로 바꾸기 위해 0xFF와 And 연산을 수행한다. 

 

예를 들어 -128이라는 값을 가진 Byte를 생각해보자. 이 Byte는 바이트로 표현하면 '10000000'이 된다. 이를 0xFF 즉 '11111111'과 And 연산을 수행해보자.

1000 0000
1111 1111
---------
1000 0000

그러면 여전히 값은 1000000이 되며, 이 값은 Unsigned Byte 에서는 128이 된다.

 

이를 확인하기 위해 128의 값을 가지는 UByte를 Byte로 변환해 출력해보면 -128이 나오는 것을 볼 수 있다.

fun main() {
  val uByte: UByte = 128U

  println("Byte: ${uByte.toByte()}") // -128 출력
}

 

UByte 뿐만 아니라, UShort, UInt, ULong 모두 내부에 Short, Int, Long을 래핑하는 형태로 구현되어 있으며, 비슷한 방식을 통해 데이터의 변환을 수행한다.

public value class UShort ... internal constructor(@PublishedApi internal val data: Short) : Comparable<UShort>
public value class UInt ... internal constructor(@PublishedApi internal val data: Int) : Comparable<UInt> 
public value class ULong ... internal constructor(@PublishedApi internal val data: Long) : Comparable<ULong>

 

정리

  • Unsigned 타입을 통해 0보다 크거나 같은 값을 다룰 수 있다.
  • Unsigned 타입은 내부에 Signed 타입을 래핑하고 있다.

 

 

반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com