Python

1-6-2. 함수호출로 계산시간을 단축해보기.

함수호출은
여러번 어떤 내용을 불러들이거나 저장해
시간이 오래걸리는 작업들을 해결해 나가는 작업을 다룹니다.

재귀 함수에 함수호출 적용해보기

재귀 : 자기 자신을 호출하는 것
자기 자신을 호출하여 연산을 진행하는 함수를 의미합니다.
중학교 수학시간에 배운 적 있는 팩토리얼을 재귀함수를 통해 표현하기

팩토리얼 수학 식
[n! = n * (n-1) * (n-2) * … * (n-(n-2)) * 1]

# 함수 선언

def factorial(n):
	# n이 0일 때 1을 반환
	if n == 0:
		return 1
	else:
		return n * factorial(n-1)

# 함수 호출하기
print("1!:", factorial(1))
print("3!:", factorial(3))
print("100!:", factorial(100))
함수호출

재귀 함수 문제

재귀함수는 특정한 상황(매우 많은 반복 처리)
이면 너무 많은 반복을 실행하는 것이 문제가 될 수 있습니다.

def fibonacci(n):
	if n== 1:
		return 1
	elif n == 2:
		return 1
	else:
        result = fibonacci(n-1) + fibonacci(n-2)
		print(result)
	return result
 
print(fibonacci(50))

위의 코드를 실행해 보면
컴퓨터는 엄청나게 많은 연산을 하는것이 보이는데
빠르게 결과를 주지 못하는 것을 알 수 있습니다.
이와 관련된 내용을 확인해보기 위해
몇 번의 계산을 컴퓨터가 진행하는지 확인해보기

# 함수호출
counter = 0
def fibonacci(n):
	# 어떤 피보나치 수를 구하는지 출력
	print("fibonacci({})를 구합니다.".format(n))
	global counter
	    counter += 1
	if n== 1:
		return 1
	elif n == 2:
		return 1
	else:
		return fibonacci(n-1) + fibonacci(n-2)

fibonacci(35)
print("fibonacci(35) 계산에 활용된 덧셈 수는 {}번입니다.".format(counter))

위의 코드도 오랜 시간을 소비하여 덧셈을 한 횟수를 계산하여 줍니다.
피보나치 수열이 각각의 피보나치 수열을 덧셈을 한 번씩
이미 했던 계산이 있더라도 계산 회수가 엄청나게 많이 늘어나게 됩니다.


메모화

재귀함수의 위와 같은 문제로
읽기 쉽게 코드를 작성할 수 있으면서
같은 값은 한 번만 계산하도록 코드를 만들면
계산 속도 역시도 빨라질 것입니다.

# 메모 변수 선언

dictionary = {
	1: 1,
	2: 1
}

def fibonacci(n):
    if n in dictionary:
        return dictionary[n]
    else:
        output = fibonacci(n-1) + fibonacci(n-2)
        dictionary[n] = output
        return output

print("fibonacci(50): ", fibonacci(50))
print(dictionary)

메모화를 사용하면 곧바로 값이 출력될만큼 연산이 줄어들게됩니다.
dictionary를 출력해보면 어떤 값들이 연산에 사용되었는지가 출력됩니다.

조기 리턴

과거 프로그래밍에는 변수는
반드시 앞 쪽에 몰아서 선언하고
리턴은 반드시 뒤에서 해얗나느 규칙이있었지만
요즘에는 필요할 때 하면 된다는 식으로 변경되었습니다.
과거의 함수 흐름의 끝에 리턴을 적기 위해 코드를 작성하였지만
이제 흐름 중간에 return 키워드를 사용하는 것조기리턴이라고 합니다.

조기 리턴 예시

def fibonacci(n):
	if n in dictionary:
		# 메모되어 있으면 메모된 값 리턴
		return dictionary[n]
	#메모 안되어있으면 값을 계산
	output = fibonacci(n-1) + fibonacci(n-2)
	dictionary[n] = output
	return output

위와 같이 if 와 else를 사용하여
흐름을 명확히 구분하기 보다
이후 코드를 실행하는 상황을 막아
return을 해준 뒤
else를 없이 코드를 사용할 수 있도록
만들어주는 방식입니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다