나의 답)
import Foundation
func solution(_ n:Int, _ t:Int) -> Int {
var result = n
for i in 1...t {
result *= 2
}
return result
}
한 시간의 두배만큼 증식하는거면 경과한 시간마다 X2를 해주면 되겠다 싶어 바로 for문
이 생각나서 초기 세균의 수를 result
값에 지정하고,
반복문을 통해 세균 마릿 수가 몇 마리던 하나씩 모두 2
를 곱해주었다.
값은 잘 맞았고 정답이긴 했는데, 다른 사람의 풀이를 보다가 pow
라는 것을 이용해 간단히 풀었던 공식을 보게 됐다.
.
.
.
func pow(_ x: Double, _ y: Double) -> Double
매개변수
반환값
알아보니 Swift에서는 거듭제곱 연산자를 제공하지 않아서, pow 함수를 사용해야 한다고 한다.
기본적으로 pow
는 Foundation
라이브러리에 포함되어 있고, Swift에서 제공하는 제곱 함수라서 숫자의 거듭제곱을 계산할 때 사용된다고 한다.
위에서 Double타입으로 하는건 알았지만 그냥 Int로 해보고 싶었다.
역시나 되지 않았다.
오류를 확인해보니 Int
타입의 값을 Decimal
타입의 매개변수에 전달할 수 없다는 의미라고 하는데,
swift에서는 서로 다른 데이터타입을 명시적으로 변환해야하고, Int
를 Decimal
로 자동 변환하지 않는다고 한다.
swift에서 pow함수와 Decimal 타입을 함께 사용하는 이유는 Decimal 타입이 정밀한 실수 연산을 지원하기 때문이라고 한다.
Decimal은 고정 소수점 타입으로, 부동 소수점 타입(Double이나 Float)과 다르게 정확한 계산이 필요한 경우 사용된다고 한다.
주로 금융 계산처럼 높은 정밀도가 필요한 상황에서 유용하다고 .. 오..
.
.
.
아무튼 Fix를 눌러보았고 이렇게 Decimal이 붙었다.
근데 왜 num1 만 감싸고 num2는 버려둔건지 모르겠다.
바로 이럴 때 공식문서를 봐야 한다.
Decimal
로 감싸는 이유는 pow
함수의 첫 번째 매개변수가 Decimal
타입이어야 하기 때문인 것인데,
Swift는 매개변수의 타입에 맞는 값을 요구하고 num1
만 Decimal
로 변환한 이유는 다음과 같은 규칙 때문이다.
pow
함수의 요구사항pow
함수가 Decimal
타입에서 동작하려면, 첫 번째 매개변수가 Decimal
이어야 하고,
두 번째 매개변수(num2
)는 Int
타입이어도 된다.
이건 Swift가 pow
의 Decimal
확장 구현에서 두 번째 매개변수를 정수로 허용하기 때문이라고 한다.
Decimal
확장 pow
함수의 정의func pow(_ base: Decimal, _ exponent: Int) -> Decimal
base
는 Decimal
타입이어야 함.exponent
는 Int
타입이어야 함.따라서 num1
만 Decimal
로 변환하면, pow
함수의 정의와 일치하므로 올바르게 작동된다.
num2
는 변환하지 않아도 되는가pow
함수의 두 번째 매개변수(exponent
)는 이미 Int
타입이다.
따라서 별도의 변환 없이도 함수 정의에 적합하다는 것인데, 그래서 num2
는 추가 작업 없이 그대로 사용이 가능하다.
import Foundation
let num1 = 2 // Int 타입
let num2 = 3 // Int 타입
let result = pow(Decimal(num1), num2) // num1만 Decimal로 변환
print(result) // 8
num1
(Int
) → Decimal(num1)
로 변환: Decimal
타입 요구를 만족시킴.num2
(Int
) 그대로 사용: 함수 정의에서 허용되므로 변환 불필요.만약 모든 매개변수를 Decimal
로 통일하고 싶다면, num2
도 명시적으로 변환할 수 있다.
let num1 = 2
let num2 = 3
let result = pow(Decimal(num1), Decimal(num2)) // num2도 Decimal로 변환
print(result) // 8
이 경우, 정확히 동일한 결과를 얻을 수 있지만 불필요한 변환 작업이 추가된다.
내 코드에서 Decimal
로 num1
만 감싼 것은 함수의 정의를 만족시키는데 충분하기 때문에 굳이 두개를 다 감쌀 필요가 없었다.
불필요한 변환은 피하고 필요한 부분만 변환하는 것이 Swift에서 권장되는 방법이라고 한다.
진짜 swift가 대학을 갔다면 카이스트였을 것 같다. 어마무시하다.
pow
함수는 기본적으로 Double
타입의 매개변수를 받도록 설계되어 있어서,
Int
타입인 num1
과 num2
를 Double
로 변환한 후 사용하는 것도 가능하다.
Decimal
과 지금Double
의 경우 차이Double
을 사용한 경우
Decimal
을 사용한 경우
Double
보다 느릴 수 있음.pow
의 Decimal
확장 등).바로 이렇게 풀었다.
func solution(_ n: Int, _ t: Int) -> Int {
return n * Int(pow(2.0, Double(t)))
}
pow(2.0, Double(t))
는 2
를 t제곱
한 값을 반환하니 세균이 1시간마다 두 배가 되어서, t
시간 후에는 2^t
배로 증식하게 된다.
그리고 처음 세균 수 n
에 2^t
를 곱해 최종 세균 수를 계산하면 되는 것이다.
코드를 통해 수학도 하고 ... 여러모로 swift 덕분에 많이 배운다.
n
: 세균의 개수 (Int 타입)t
: 시간 (Int 타입)pow(2.0, Double(t))
pow
함수는 거듭제곱을 계산하는 함수인거는 이제 공부를 해서 알았고,
여기서는 2를 t번 곱한 값을 계산하는 것인데,
만약 t
가 3
이라면 pow(2.0, 3)
은 2^3 = 8
이 된다는 것이다.
Double(t)
는 Int 타입이기 때문에 pow
함수의 두 번째 인자는 Double
타입이어야 한다.
그래서Double(t)
로 t
를 Double
타입으로 변환했다.
Int
타입의 t
를 Double
타입으로 변환하는 이유는 pow
함수가 Double
타입의 값을 요구하기 때문이다.
Int
는 정수고 Double
은 실수라서 두 타입 간에는 직접적인 연산이 불가능하다.
그래서 t
를 Double(t)
로 명시적으로 변환해주는 것이라고 보면 된다.
넘어가서, Int(pow(2.0, Double(t)))
pow
함수는 Double
타입의 값을 반환했지만 n
은 Int
타입이기 때문에 pow(2.0, Double(t))
의 현재 결과도 Double
이다.
그럼 이걸 Int 타입으로 변환해야 한다. 정답은 정수이니까.
그래서 Int()로 감싸서 정수로 변환한 것이다.
n * Int(pow(2.0, Double(t)))
그리고 마지막으로 초기 세균의 수 n에 2^t를 곱한 결과가 계산된다.
이 연산은 n
이 처음 주어진 세균의 수고, t
는 시간에 따라 2배씩 증가하는 세균 수의 증가율을 나타내기 때문이다.
그렇게 최종적으로 계산된 세균의 수를 return으로 반환해주면 ,,
굿
오늘 pow 함수에 대해 공부하면서 여러 가지 중요한 내용을 알게 되었다.
수학을 모르다보니 제곱근과 거듭제곱의 개념이 혼동되기도 했었다. ㅎㅎ....
공부하면서 pow 함수는 두 숫자의 거듭제곱을 계산하는 함수라는 것도 확인했고, 기본적으로 Double 타입의 값을 받는 함수라는 것과 Int 타입의 값을 넘기려면 Double로 변환해줘야 한다는 것을 배웠다.
아까 Int 타입의 num1과 num2를 Double(num1)과 Double(num2)로 변환하여 사용해야 한다는 점에서 타입 변환에 대한 이해가 좀 필요했어서 시간이 좀 걸린 듯 하다.
그리고 pow 함수는 반환 값이 항상 Double 타입이라서 계산된 결과가 소수점을 포함하는 실수로 나온다는 점도 알게 됐는데, 만약 2의 3제곱을 계산하면 8이 아닌 8.0이 출력된다.
그리고 위에 말했던 Decimal 타입을 사용해 더 정밀한 계산을 할 수도 있다는 것도 배우고, 그 사용법을 알아봤다. (Fix로 인해 알게 되었지만..)
다만 Decimal을 사용할 경우 성능에 약간의 영향이 있을 수 있기 때문에, 일반적인 경우에는 Double 타입을 사용하는 것이 더 효율적이라고 한다. 오호.
아무튼 주말에는 과제를 잠시 떠나 이렇게 문제를 푸는게 리프레시 되는 기분이라 좀 좋은 것 같기도.