티스토리 뷰

Tech/Swift

스위프트 오버플로우 연산

Ellie Kim 2020. 9. 20. 04:01

leetcode.com/problems/string-to-integer-atoi

위 알고리즘 문제를 풀다가 스위프트 오버플로우 연산에 대해 궁금해졌습니다.

 

범위 넘어가는 작업을 처리하다가 스위프트에 오버플로우 연산에 대해 궁금해졌고 공부하고 정리해야겠다 생각이 들었습니다.

 

*문제에서 제약 조건

Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231,  231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned.

32 비트 부호 있는 정부 범위 내에서만 정수를 저장할 수 있는 환경을 다루고 있다고 가정합니다. 숫자 값은 -2^31 에서 2^31-1 사이고 표현 가능한 값의 범위를 벗어나면 INT_MAX(2^31-1) 또는 INT_MIN (-2^31)이 반환되어야 합니다.

 

일단 저는 스위프트 오버플로우 연산이 있다는 것은 알았지만 한 번도 사용한 적이 없었어요. 

(자랑) 

 

오버플로우 연산자

스위프트에서 정수 상수 또는 변수에 가질 수 없는 값을 숫자를 삽입하려고 하면 기본적으로 오류를 냅니다.

이 오버플로우 연산자는 너무 크거나 너무 작은 숫자로 작업할 때(가질 수 있는 값의 경계에 있을 때)

추가적으로 안전하게 할 수 있도록 해줍니다.

 

예를 들어 Int16 정수는 -32768과 32767사이에 값을 가질 수 있습니다.

Int16 상수 또는 변수는 범위 밖의 숫자의 값이 들어오게 되면 오류가 발생합니다.

var potentialOverflow = Int16.max
// potentialOverflow equals 32767, which is the maximum value an Int16 can hold

potentialOverflow += 1
// this causes an error

값이 너무 크거나 작을 때 대해서 오류 처리를 제공하면 가질 수 있는 값의 경계에 있는 조건을 코딩할 때 훨씬 더 많은 유연성을 제공할 수 있습니다.

 

즉 오류를 트리거하는 대신에 가능한 비트 수를 자르고 싶은 경우는 오버 플로우 연산자를 사용하면 됩니다.

이는 모두 &로 시작합니다.

 

&+ 더하기 오버플로우

&- 빼기 오버플로우

&* 곱하기 오버플로우

 

값 오버플로우

숫자는 양의 방향과 음의 방향으로 오버플로우 될 수 있습니다.

 

더하기 오버플로우 연산자(&+)를 사용해 부호없는 정수가 양의 방향으로 오버플로우 되는 예제를 살펴봅시다.

var unsignedOverflow = UInt8.max
// unsignedOverflow equals 255, which is the maximum value a UInt8 can hold

unsignedOverflow = unsignedOverflow &+ 1
// unsignedOverflow is now equal to 0

변수 unsignedOverflow는 Uint8은 보유할 수 있는 최댓값으로 초기화가 됩니다. (255, 이진수로는 11111111) 

다음 오버플로우 더하기 연산자(&+)를 사용해 1 증가합니다.

아래 이미지 다이어그램에 표시된 것처럼 UInt8이 가질 수 있는 크기보다 커 가능 범위를 넘어 오버플로우 됩니다.

더하기 오버플로우 연산을 통해 더해진 후 UInt8에 남아있는 값은 0 이진수로는 00000000입니다.

 

부호 없는 정수가 음의 방향으로 오버플로우 될 때도 비슷한 상황이 발생합니다.

다음은 빼기 오버플로우 연산자(&-)가 사용되는 예입니다.

var unsignedOverflow = UInt8.min
// unsignedOverflow equals 0, which is the minimum value a UInt8 can hold

unsignedOverflow = unsignedOverflow &- 1
// unsignedOverflow is now equal to 255

변수 unsignedOverflow는 Uint8은 보유할 수 있는 최솟값으로 초기화가 됩니다. (0, 이진수로는 00000000)

다음 오버플로우 빼기 연산자(&-)를 사용해 1 감소합니다.

아래 이미지 다이어그램 과 같이 숫자가 넘쳐서 11111111 또는 255로 바뀝니다.

 

 

부호 있는 정수에 대해서도 오버플로우가 발생합니다.

부호 있는 정수에 대한 모든 더하기 및 빼기는 비트 bitwise fashion로 수행되며

부호 비트는 비트 왼쪽 및 오른쪽 시프트 연산자와 같이 숫자의 일부로 포함됩니다.

var signedOverflow = Int8.min
// signedOverflow equals -128, which is the minimum value an Int8 can hold

signedOverflow = signedOverflow &- 1
// signedOverflow is now equal to 127

Int8이 보유할 수 있는 최소값은 -128 또는 이진수로는 10000000입니다.

빼기 오버플로우 연산자(&-)를 통해 1빼면 01111111이 되며

이는 부호비트를 토글 하고 UInt8이 보유할 수 있는 최대 양수 값 127을 나타냅니다.

결론은 부호있는 정수와 부호 없는 정수 모두

양수 방향의 오버플로우에서는 최대값에서 최솟값으로 돌아가고

음의 방향 오버플로우에서는 최솟값에서 최댓값으로 돌아갑니다.

 

docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html

'Tech > Swift' 카테고리의 다른 글

스위프트 mutating 키워드  (0) 2020.11.12
스위프트 배열 크기  (0) 2020.11.09
스위프트 비트 연산자  (0) 2020.09.18
dropFirst(_:), removeFirst(_:) 살펴보기  (1) 2020.09.16
스위프트 Identifiable 프로토콜  (0) 2020.06.16
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함