СЦБИСТ - сайт железнодорожников №1

СЦБИСТ - сайт железнодорожников №1 (https://scbist.com/)
-   Java (https://scbist.com/java/)
-   -   Функция вычисления факториала node.js (https://scbist.com/java/50244-funkciya-vychisleniya-faktoriala-node-javascript.html)

Вы просматриваете версию для печати. Если вы хотите увидеть статью полностью - перейдите по ссылке

Admin 03.07.2018 10:40

Функция вычисления факториала node.js
 
В Node.js есть несколько способов реализации функции вычисления факториала. Рассмотрю все варианты — от простого до оптимизированного.

 
Содержание

1. Итеративный способ (рекомендуемый)


Самый эффективный и безопасный способ:

PHP код:

function factorialIterative(n) {
    if (
n < 0) throw new Error('Факториал определён только для неотрицательных чисел');
    if (
n === 0 || n === 1) return 1;
    
    
let result = 1;
    for (
let i = 2; i <= n; i++) {
        
result *= i;
    }
    return 
result;
}

// Использование
console.log(factorialIterative(5)); // 120
console.log(factorialIterative(10)); // 3628800 


2. Рекурсивный способ


Классический, но с ограничениями:
Ограничение: для больших n (> 10000) может вызвать переполнение стека.

PHP код:

function factorialRecursive(n) {
    if (
n < 0) throw new Error('Факториал определён только для неотрицательных чисел');
    if (
n === 0 || n === 1) return 1;
    return 
n * factorialRecursive(n - 1);
}

// Использование
console.log(factorialRecursive(5)); // 120 

3. Оптимизированный рекурсивный (хвостовая рекурсия)


PHP код:

function factorialTailRecursive(n, accumulator = 1) {
    if (
n < 0) throw new Error('Факториал определён только для неотрицательных чисел');
    if (
n === 0 || n === 1) return accumulator;
    return 
factorialTailRecursive(n - 1, n * accumulator);
}

// Использование
console.log(factorialTailRecursive(5)); // 120 

4. С использованием BigInt (для очень больших чисел)


PHP код:

function factorialBigInt(n) {
    if (
n < 0) throw new Error('Факториал определён только для неотрицательных чисел');
    if (
n === 0 || n === 1) return 1n;
    
    
let result = 1n;
    for (
let i = 2n; i <= n; i++) {
        
result *= i;
    }
    return 
result;
}

// Использование
console.log(factorialBigInt(20)); // 2432902008176640000n
console.log(factorialBigInt(50).toString()); // Огромное число 

5. С мемоизацией (кэширование результатов)


PHP код:

const factorialMemo = (function() {
    const 
cache = { 0: 1, 1: 1 };
    
    return function 
factorial(n) {
        if (
n < 0) throw new Error('Факториал определён только для неотрицательных чисел');
        if (
cache[n] !== undefined) return cache[n];
        
        
cache[n] = n * factorial(n - 1);
        return 
cache[n];
    };
})();

// Использование
console.log(factorialMemo(5)); // 120 (вычисляется)
console.log(factorialMemo(5)); // 120 (берётся из кэша)
console.log(factorialMemo(6)); // 720 (использует кэшированный 5!) 

6. Асинхронная версия (для неблокирующих операций)


PHP код:

async function factorialAsync(n) {
    if (
n < 0) throw new Error('Факториал определён только для неотрицательных чисел');
    if (
n === 0 || n === 1) return 1;
    
    
let result = 1;
    for (
let i = 2; i <= n; i++) {
        
result *= i;
        
// Периодически уступаем управление для других операций
        
if (i % 1000 === 0) {
            
await new Promise(resolve => setImmediate(resolve));
        }
    }
    return 
result;
}

// Использование
(async () => {
    
console.log(await factorialAsync(5)); // 120
})(); 

7. С обработкой ошибок и валидацией


PHP код:

function factorialSafe(n) {
    
// Проверка типа
    
if (!Number.isInteger(n)) {
        throw new 
TypeError('Аргумент должен быть целым числом');
    }
    
    
// Проверка на отрицательное значение
    
if (n < 0) {
        throw new 
RangeError('Факториал определён только для неотрицательных чисел');
    }
    
    
// Проверка на слишком большое число
    
if (n > 170) {
        throw new 
RangeError('Результат выходит за пределы Number.MAX_SAFE_INTEGER');
    }
    
    if (
n === 0 || n === 1) return 1;
    
    
let result = 1;
    for (
let i = 2; i <= n; i++) {
        
result *= i;
    }
    return 
result;
} 

Сравнение производительности


PHP код:

const n = 100;

console.time('Итеративный');
factorialIterative(n);
console.timeEnd('Итеративный');

console.time('Рекурсивный');
factorialRecursive(n);
console.timeEnd('Рекурсивный');

console.time('Мемоизация');
factorialMemo(n);
console.timeEnd('Мемоизация'); 

Рекомендации:


Для большинства случаев используйте итеративный способ — он быстрый и безопасный

Для больших чисел (> 170) используйте BigInt

Для многократных вычислений используйте мемоизацию

Для академических целей подойдёт рекурсивный способ

В production всегда добавляйте валидацию входных данных

Помните, что факториал быстро растёт: 20! ≈ 2.43e18, что уже превышает безопасный предел для Number в JavaScript (2^53 - 1).


Часовой пояс GMT +3, время: 07:08.

Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot


Яндекс.Метрика