본문 바로가기
프로그래밍 팁/Swift

1-9. Swift - 숫자 타입 변환(Numeric Type Conversion) 문법 개념 정리

by Archivers 2020. 11. 7.

 

숫자 타입 변환(Numeric type conversion)

정수형 상수나 변수를 선언하는 일반적인 경우에는 정수 타입(Int)을 사용하는 것을 권장합니다. 심지어 해당 값이 음의 정수여도 말입니다. 기본적으로 Int 타입을 사용함으로써 코드에 작성된 정수형 상수와 변수는 상호운용이 가능하게 되며, 정수 리터럴 값의 타입을 추론하는 것도 가능해집니다.

 

외부 소스의 데이터 크기가 분명히 정해져 있거나, 성능, 메모리 사용, 최적화 작업 등 분명한 목적이 있는 경우에만 다른 정수 타입을 사용하는 것을 권장합니다. 분명한 목적을 가지고 특정한 정수 타입을 사용함으로써 실수로 값이 초과되는 것을 막을 수 있으며, 사용되는 데이터의 특성을 암묵적으로 명시할 수 있다는 장점이 있습니다.

 

 

정수 변환(Integer conversion)

정수 타입의 상수 또는 변수에 저장될 수 있는 숫자의 범위는 각 숫자 타입에 따라 다릅니다. Int8 타입의 상수 또는 변수는 -128부터 127까지의 범위에 속하는 정수를 저장할 수 있습니다. 반면 UInt8 타입의 상수 또는 변수는 0부터 255까지의 범위에 속하는 정수를 저장할 수 있습니다. 만약 각 정수 타입의 범위에 속하지 않는 값을 해당 상수 또는 변수에 저장하려고 하면 컴파일할 때 오류가 발생합니다.

let cannotBeNegative: UInt8 = -1
let tooBig: Int8 = Int8.max + 1

 

위 코드는 다음과 같이 글로 표현할 수 있습니다.

 

cannotBeNegative라는 이름의 상수를 선언하고자 합니다. 이 상수의 타입은 UInt8로 명시하고 있으며 이 상수에는 -1을 저장하고자 합니다. 하지만 UInt8은 부호가 없는 8비트 정수형 타입이기 때문에 음의 정수는 저장할 수 없습니다. 따라서 이 선언문은 오류를 발생시킵니다.

tooBig이라는 이름의 상수를 선언하고자 합니다. 이 상수의 타입은 Int8로 명시하고 있으며, Int8 타입의 정수가 가질 수 있는 최댓값에 1을 더한 값을 이 상수에 저장하고자 합니다. 참고로 Int8 타입은 -128부터 127까지의 범위에 속하는 값을 가집니다. Int8의 최댓값은 127입니다. 이 값에 1을 더하면 128이 되고, 128은 Int8 타입의 범위를 벗어나게 됩니다. 따라서 이 값을 해당 상수에 저장할 수 없으므로 이 선언문은 오류를 발생시킵니다.

 

각 숫자 타입마다 저장할 수 있는 값의 범위가 다르기 때문에 상황에 따라 적절한 숫자 타입 변환 방식을 사용해야 합니다. 이를 통해 잠재적인 변환 오류를 방지할 수 있으며 코드를 작성함에 있어서 타입을 변환하고자 할 때 사용자의 의도를 분명히 명시할 수 있습니다.

 

숫자 타입을 변환하기 위해서는 우선 기존의 값을 토대로 변환하고자 하는 새로운 값을 초기화해야 합니다.

let twoThousand: UInt16 = 2_000
let one: UInt8 = 1
let twoThousandAndOne = twoThousand + one

 

위 코드는 다음과 같이 글로 표현할 수 있습니다.

 

twoThousand라는 이름의 상수를 선언하고자 합니다. 이 상수의 타입은 UInt16으로 정하였으며, 이 상수에 2_000(즉 2000)을 저장하고자 합니다. one이라는 이름의 상수를 UInt8 타입으로 선언하고자 하며, 이 상수에 1을 저장하고자 합니다.

그리고 twoThousand 상수의 값과 one 상수의 값을 더한 결과값을 twoThousandAndOne 상수에 저장하고자 합니다.

 

하지만 이 마지막 선언문은 오류를 발생하게 됩니다. twoThousand 상수와 one 상수는 다른 정수 타입을 가지고 있기 때문입니다. 즉, Uint16과 UInt8 타입은 서로 다르므로 덧셈을 할 수 없습니다.

let twoThousandAndOne = twoThousand + UInt16(one)

 

반면 위 코드에서는 one 상수를 괄호 안에 넣고 괄호 앞에 UInt16을 적은 다음, twoThousand 상수와 더하고 있습니다. UInt16()안에 one 상수를 넣음으로써 UInt8 타입인 one 상수의 값이 UInt16 타입으로 변환하게 되고, 이로써 두 상수 간의 덧셈이 가능해집니다. 즉, twoThousand 상수의 값과 one 상수의 값을 UInt16 타입으로 변환한 값을 더하여 twoThousandAndOne라는 이름의 상수에 저장하고자 합니다. 두 상수를 더한 값의 타입 역시 UInt16이 될 것입니다. UInt16과 UInt16 타입의 두 상수의 값을 서로 더했기 때문입니다. 이 선언문은 오류를 발생시키지 않습니다.

 

앞에서 '숫자 타입을 변환하기 위해서는 우선 기존의 값을 토대로 변환하고자 하는 새로운 값으로 초기화(initialize)해야 합니다.'라고 서술하였습니다. 이처럼 기존의 값을 괄호 안에 넣고 괄호 앞에 변환하고자 하는 타입을 적으면 해당 Swift 타입의 초기화 함수(initializer; 또는 이니셜라이저)가 호출됩니다. 그리고 이 초기화 함수에 기존의 값을 대입함으로써 새로운 값이 변환되어 반환됩니다. UInt16 타입은 UInt8 타입의 값을 수용할 수 있는 초기화 함수를 가지고 있습니다. UInt16 타입이 UInt8 타입보다 훨씬 더 큰 값의 범위를 가지기 때문입니다. UInt8 타입의 값의 범위는 0~255이며, UInt16 타입의 값의 범위는 0~65,535입니다. UInt8 타입의 범위가 UInt16 타입의 범위에 포함된다고 보면 됩니다. 따라서 UInt8 타입에서 UInt16 타입으로 변환이 이루어질 수 있습니다. 물론 어느 타입이나 변환할 수 있는 것은 아닙니다.

 

 

정수 및 부동소수점 변환(Integer and floating-point conversion)

정수 타입의 값과 부동소수점 타입의 값 사이의 변환의 경우에는 주의할 점이 있습니다.

let three = 3
let pointOneFourOneFiveNine = 0.14159
let pi = Double(three) + pointOneFourOneFiveNine

 

위 코드는 다음과 같이 글로 표현할 수 있습니다.

 

숫자 3을 three 상수에 저장합니다. 이 과정에서 타입은 명시하지 않았습니다.

0.14159을 pointOneFourOneFiveNine 상수에 저장합니다. 이 과정에서 타입은 명시하지 않았습니다.

그리고 three 상수를 Double 타입으로 변환한 다음 pointOneFourOneFiveNine 상수와 더한 결과값을 pi 상수에 저장하고자 합니다.

 

three 상수의 타입이 명시되지 않았으나 숫자 3을 저장한다고 명시하였기 때문에 Swift는 타입 추론을 하게 됩니다. 숫자 3은 정수이기 때문에 Swift는 three 상수의 타입을 정수로 추론합니다. 그리고 pointOneFourOneFiveNine 상수의 경우에는 0.14159가 부동소수점 값입니다. 지난 글에서 서술되었듯이 부동소수점 값에는 Double과 Float 두 종류가 있습니다. Double이 Float보다 더 큰 값의 범위를 가진다고 보면 됩니다. 따라서 이 경우 Swift는 0.14159를 Double 타입으로 여기고, 따라서 pointOneFourOneFiveNine 상수의 타입을 Double로 추론합니다.

 

다음으로 three 상수와 pointOneFourOneFiveNine 상수를 더하고자 합니다. 두 상수는 타입이 서로 다릅니다. 그렇다면 어느 상수의 타입을 변환해야 할까요? three 상수의 타입을 변환하면 됩니다. 만약 pointOneFourOneFiveNine 상수의 값을 정수 타입으로 변환하면 0.14159가 정수로 바뀌게 되므로 값이 달라집니다. 따라서 일부러 기존의 값을 다르게 하는 목적이 아니라면, 0.14159는 그대로 유지하고 three 상수의 값인 3을 부동소수점으로 변환하는 것이 낫습니다. 정수 3을 부동소수점으로 변환하면 3.0이 되기 때문에 값에는 변화가 없습니다. 따라서 Double(three) + pointOneFourOneFiveNine는 3.0 + 0.14159이 됩니다. 결과값은 3.14159가 되고 이 값을 pi 상수에 저장합니다.

 

부동소수점 타입을 정수 타입으로 변환하는 것도 타입을 분명히 명시해야 합니다. 정수 타입은 Double 또는 Float 타입으로 초기화될 수 있습니다.

let integerPi = Int(pi)

 

위 코드는 다음과 같이 글로 표현할 수 있습니다.

 

pi 상수의 값을 정수 타입으로 변환한 다음 integerPi 상수에 저장하고자 합니다. pi 상수의 값은 3.14159입니다. 이 값을 정수로 변환하면 3이 됩니다. 따라서 integerPi 상수에는 3이 저장됩니다.

 

이처럼 부동소수점 값을 정수 값으로 변환할 때는 값이 줄어들게 됩니다. 4.75를 정수 값으로 변환하면 4가 되며, -3.9를 정수 값으로 변환하면 -3이 됩니다. 참고로 -3.9를 정수 값으로 변환하면 -4가 아니라 -3입니다. 음의 정수와 양의 정수는 방향이 반대이기 때문입니다.

 

 

 

 

 

이 글은 Apple이 제공하는 'The Swift Programming Language 5.2 버전' (https://swift.org)을 번역 및 참고하여 작성하였습니다.

댓글