Мне нравится тот факт, что есть так много способов создать последовательность Фибоначчи в JS .Я постараюсь воспроизвести некоторые из них.Цель состоит в том, чтобы вывести последовательность на консоль (например, {n: 6, fiboNum: 8}
)
Good 'ol closure
// The IIFE form is purposefully omitted. See below.
const fiboGenClosure = () => {
let [a, b] = [0, 1];
let n = 0;
return (fiboNum = a) => {
[a, b] = [b, a + b];
return {
n: n++,
fiboNum: fiboNum
};
};
}
// Gets the sequence until given nth number. Always returns a new copy of the main function, so it is possible to generate multiple independent sequences.
const generateFiboClosure = n => {
const newSequence = fiboGenClosure();
for (let i = 0; i <= n; i++) {
console.log(newSequence());
}
}
generateFiboClosure(21);
Необычный генератор ES6
Аналогично схеме замыкания, приведенной выше, с использованием преимуществ функции генератора и для ... цикла.
// The 'n' argument is a substitute for index.
function* fiboGen(n = 0) {
let [a, b] = [0, 1];
while (true) {
yield [a, n++];
[a, b] = [b, a + b];
}
}
// Also gives a new sequence every time is invoked.
const generateFibonacci = n => {
const iterator = fiboGen();
for (let [value, index] of iterator) {
console.log({
n: index,
fiboNum: value
});
if (index >= n) break;
}
}
generateFibonacci(21);
Рекурсия вызова Tail
Это немного сложно, потому что, в конце 2018 года, оптимизация TC все еще остается проблемой.Но, честно говоря - если вы не будете использовать какие-либо хитрые трюки, чтобы позволить стандартному движку JS использовать действительно большие числа, у него закружится голова и он скажет, что следующим числом Фибоначчи будет «Бесконечность» на итерации 1477. Возможно, стек где-то переполнитсявокруг итерации 10 000 (сильно зависит от браузера, памяти и т. д.).Вероятно, может быть дополнен блоком try… catch или проверьте, достигнут ли «Infinity».
const fibonacciRTC = (n, i = 0, a = 0, b = 1) => {
console.log({
n: i,
fibonacci: a
});
if (n === 0) return;
return fibonacciRTC(--n, ++i, b, a + b);
}
fibonacciRTC(21)
Он может быть записан как однострочный, если мы отбросим вещь console.log
и просто вернем число:
const fibonacciRTC2 = (n, a = 0, b = 1) => n === 0 ? a : fibonacciRTC2(n - 1, b, a + b);
console.log(fibonacciRTC2(21))
Важное примечание!
Как я узнал, прочитав эту статью mathIsFun , последовательность Фибоначчи действительна для отрицательных чисела также! Я попытался реализовать это в приведенной выше форме рекурсивного вызова:
const fibonacciRTC3 = (n, a = 0, b = 1, sign = n >= 0 ? 1 : -1) => {
if (n === 0) return a * sign;
return fibonacciRTC3(n - sign, b, a + b, sign);
}
console.log(fibonacciRTC3(8)); // 21
console.log(fibonacciRTC3(-8)); // -21