자바스크립트에서 Fibonacci 시리즈를 가장 빠르고 효율적으로 계산하는...

자바스크립트에서 Fibonacci 시리즈를 가장 빠르고 효율적으로 계산하는...

archive

피보나찌가 뭐야?

피보나치 수열 또는 피보나치 수열은 앞의 두 숫자의 값을 더하여 계산되는 수열이다. 그것은 황금비율이라고도 알려져 있고 자연에서 널리 발견됩니다.

0인 지수 n = 0으로 시작하는 수열과 1인 지수 n = 1로 계산한다.

따라서 다음 원소(n = 2)는 1 (이전 값 0 + 1)이다. 제3원소(n=3)는 2(1+1), 제4원소(1+2), 제5원소(2+3), 제3원소(n=3)다.

공식은 다음과 같이 정의된다.

F(n) = F(n-2) + F(n-1) // n > 2인 경우(예: F(2) = F(0) + F(1)

처음 21개의 숫자는 다음과 같습니다.

0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765

모든 알고리즘은 동일한 입력에 대해 동일한 값을 반환해야 합니다. 기본적으로 시퀀스 인덱스 번호(n)를 통과시켜 그에 상응하는 값을 얻는 것이 목표입니다. 예:

fibonacci(0); // 반환: 0 fibonacci(1); // 반환: 1 fibonacci(2); // 반환: 1 fibonacci(5); // 반환: 5 fibonacci(10); // 반환: 55 fibonacci(20); // 반환: 6765

재귀 알고리즘

가장 간단하고 쉬운 알고리즘은 재귀 알고리즘입니다. 모든 재귀 알고리즘은 동일한 원리로 작동합니다. 함수는 자신을 호출하고 이전 계산의 결과를 전달합니다.

함수 피보나치(fibonacci) { (수치 === 0)이 0을 반환하는 경우; (수치 === 1) 반환 1인 경우; 리턴 피보나치(fibonacci - 2) + 피보나치(fibonacci - 1); }

재귀 알고리즘의 단점은 매번 이전의 모든 값을 다시 계산해야 한다는 것입니다. 따라서, 그것은 별로 효과적이지 않고 시간 복잡성은 지수적이다: O(2^N) 의 명제

메모화가 있는 재귀 알고리즘

우리는 메모라이제이션이라 불리는 기술로 이전 알고리즘의 속도를 획기적으로 높일 수 있습니다. 기본적으로 이전 계산 값을 메모리에 보관합니다. 즉, 이전 결과를 저장하기 위해 캐시 변수를 추가로 사용합니다.

캐시[원소] 반환 캐시[원소]만 추가하면 됩니다. 이렇게 캐시[원소]를 시작하고 다음과 같이 전달하면 됩니다.

함수 fibonacci(포함수, 캐시 = []) { (수치 === 0)이 0을 반환하는 경우; (수치 === 1) 반환 1인 경우; 캐시[캐시]를 반환하는 경우 캐시[cash] = 피보나치(fibonacci - 2, 캐시) + 피보나치(fibonacci - 1, 캐시); 캐시를 반환하다[반환하다]; }

반복 알고리즘

메모화가 포함된 재귀 알고리즘은 작동하지만 여전히 느립니다. 따라서, 우리는 코드를 리팩터링하고 반복 알고리즘을 사용할 수 있다.

우리는 단지 앞의 두 원소인 0과 1은 계산할 수 없고 다음 두 원소 모두 앞의 두 원소의 합이라는 것을 기억할 필요가 있다. n원소를 얻기 위해 필요한 것을 얻을 수 있는 for 루프를 할 수 있다.

함수 피보나치(fibonacci) { 구성 시퀀스 = [0, 1]; (i = 2; i <= 요소, i++) { 시퀀스[i] = 시퀀스[i - 2] + 시퀀스[i - 1]; } 순서를 되돌리다[돌리다]; }

벤치마크

n = 20번 원소에 대해 nonacci 함수를 호출하는 재귀 알고리즘의 횟수를 세면 21891 호출이 나온다!

메모화는 동일한 요소에 대한 여러 함수 호출을 39로 줄일 수 있습니다. 인상적입니다.

그러나 두 재귀 알고리즘 모두 반복 알고리즘과는 거리가 멀다!

각 알고리즘이 연산/초 를 보여주는 벤치마킹 소프트웨어와 얼마나 빠르게 동작하는지, 즉 1초 안에 각 테스트를 실행할 수 있는 횟수를 비교할 수 있다. 높을수록 좋다. 다음은 jsben.ch에서 수행한 벤치마크 예와 결과입니다.

메모화가 적용된 fibonacci(10) 재귀 알고리즘은 반복 알고리즘 속도의 85.56%, 재귀 알고리즘은 32.08%의 성능을 각각 달성했다.

이 숫자는 n을 더 큰 숫자로 늘리면 더 내려간다. 예를 들어, fibonacci(15)는 다음과 같다.

그것은 정말 인상적이에요!

비네의 공식 보기

지금까지 우리는 피보나치 수를 계산하는 세 가지 방법을 비교했지만 더 나은 기술도 있다… 그리고 그것은 비네의 공식이다.

자크 필리프 마리 비네는 피보나치 수를 계산하는 공식을 고안한 프랑스 수학자이다. 사실, Leonhard Euler와 Abraham de Moivre는 이전에도 같은 공식을 사용했지만, Binet은 모든 영광을 얻었고, 오늘날 그 공식은 Binet의 공식으로 명명되었습니다.

이를 자바스크립트로 변환할 수 있습니다.

함수 binet(n) { return Math.round((1 + Math.sqrt(5)) / 2, n) - Math.pow((1 - Math.sqrt(5)) / Math.sqrt(5)) / Math.sqrt(5)); }

또는 몇 개의 상수 값이 있기 때문에, 예를 들어 제곱근 5는 대략 2.23606797749979 와 같다. 우리는 그것들을 미리 계산하고 공식을 다음과 같이 단순화할 수 있다.

함수 binet(n) { 반환 Math.round(Math.pow(1.618033988749895, n) - Math.pow(-0.6180339887498949, n) / 2.23606797749979); }

다시 벤치마킹

일단 Binet의 공식으로 벤치마크를 업데이트하면 결과는 다음과 같습니다.

예상대로, 비넷의 공식은 이전의 피보나치 수치에 의존하지 않기 때문에 가장 빠르다.

요약

재귀 알고리즘이 인기 있는 컴퓨터 과학 주제이고 인기 있는 인터뷰 질문일 수도 있지만, 속도와 효율 면에서, 반복 알고리즘과 비네의 공식과는 거리가 멀다. 사실, 비넷이 가장 빠릅니다.

따라서, 만약 당신이 성능을 찾고 있다면 비네의 공식을 사용하세요. 그러나 속도가 문제가 아니라면 재귀 알고리즘이 더 간단하고 우아합니다.

읽어주셔서 감사합니다.

from http://sup-poster.tistory.com/4 by ccl(A) rewrite - 2021-09-17 09:28:20