Abnormal programming
JavaScript
Comments 47
0
Круто, прикольно, но где тут новый способ? Я вижу тут лишь необычную реализацию стандартного способа.
0
А вы таки хотите способ вычисления факториала без перемножения чисел от 1 до N? Ну, можно по формуле Стирлинга, или через гамма-функцию Эйлера. Но это уже статья в другой хаб.
+12
Многие скажут, что первый способ лучше, но это не так. Во-первых, циклы уже не в тренде, сейчас модно функциональное программирование.


Аргументация уровня журнала Cosmopolitan
0
Через цикл ведь все равно будет быстрее и короче, не?
+4
Ну, такие заявления нельзя делать без тестов. Нужно замерить перформанс в каждом конкретном случае.
0
Не совсем понимаю, о каких конкретных случаях речь, я говорил о самом банальном сравнении, которое вы дали в начале.На любом тесте, который бы я не находил на jsPerf, цикл выигрывал с довольно большим отрывом. И да, я не делал заявлений, я как раз таки задал вопрос, так как самому интересно.
0
Если отвечать серьёзно, то разумеется, цикл будет быстрее рекурсии. Я не уверен, можно ли как-то оптимизировать ещё сильнее, но из наивных реализаций цикл точно самый быстрый.
+2
Чтобы не быть голословными: https://jsperf.com/fastest-factorial

(1) cycle: 3.700.000 op/sec
(2) recursion: 1.450.000 op/sec
(3) eval: 500 op/sec
+1
Возможно вам будет полезно посмотреть доклад Вячеслава Егорова, человека который участвовал в разработке V8. Узнаете много нового о перфоманс тестах в JS.
+1
А разве без теста не очевидно, что в обоих случаях выполняется одно и то же действие (перемножение чисел), только при рекурсии программа «распухает» за счёт вызова функции (самой себя) и передачи (копирования) ей данных?
0
Вообще да, но в данном случае нет. В то время, как наши космические корабли бороздят просторы вселенной, а в процессорах, компиляторах и интерпретаторах множатся неочевидные оптимизации, очевидных с точки зрения перформанса вещей становятся всё меньше. В комментарии выше я написал «разумеется», поскольку изучил вопрос и выяснил, что в современных js-движках рекурсия не оптимизирована. Без этого знания ответ не является очевидным.
+1
Возможно это и откровение с точки зрения факториала, а вот с точки зрения js кода этому творению место на свалке.
+4
Сильное заявление. Аргументировать его вы, конечно, не будете?
0
Скажите пожалуйста, а зачем в примере с рекурсией второй параметр? И что в него передается при вызове?
0
Ну, собственно, да. Иначе можно было бы написать function factorial(n){return !n? 1: factorial(n-1)}. Но в таком случае, несмотря на то, что рекурсивный вызов стоит последним, это не будет хвостовой рекурсией, потому что последним вычисляемым выражением будет значение тернарного оператора.
-1
Во-вторых, чем больше людей используют второй способ, тем быстрее в основных джаваскриптовых движках появится оптимизация

То есть давайте все ходить через лес, тогда там быстрее появится дорога.
+2
Там, где ходят люди, протаптываются тропинки этими самыми людьми. А потом там кладут асфальт и облагораживают дорожки.
0
Это если в 10 метрах уже не проложена дорога. По которой все ходят. И тут появляется такой человек, который хочет дорогу на 10 метров ближе к своему дому и говорит: ходите все через лес, в грязь, в снег, тогда через несколько лет тут будет дорога…
А имеющаяся дорога — это циклы.
+1
Я не понимаю, что Вам не нравится. Основную дорогу никто не закроет же.
-1
Ваш код настолько идеален, что изобретает новую математику: по мнению вашего алгоритма, 50! = 3. В чем тогда смысл такого запутанного кода, который ни поддерживать, ни отлаживать невозможно?
+1
Ну, в некотором смысле это действительно 3. Если быть точным, 3.0414093201713376e+64.
+2

Когда прочитал про eval ожидал что-то вроде


function factorial(n) {
    return eval(
        Array.apply(0, Array(n + 1))
            .map(Number.call.bind(Number))
            .slice(1)
            .join('*')
    )
}

К сожалению, движки недостаточно оптимизированы, чтобы eval был быстрее обычного цикла.

0
Кстати да, я думал об этом, но потом самомодифицирующийся код захватил мою голову.
0
Господи боже, мы наконец-то дожили до сложения чисел с помощью JQuery!
Сарказм, конечно же, но все-таки…
+1
var React = require("react");

var Factorial = React.createClass({
    render: function(){
        var result = this.props.result || 1,
            n = this.props.n;
        if(!n){
        return <span>{result}</span>
    }else{
        return <Factorial n={n - 1} result={result*n}/>
    }
    }
});
module.exports = Factorial;

Вот это вот? Выглядит солиднее? С кусками разметки? Это как в современном мире называется — шутка, сарказм или что?

+2
Как-то слишком примитивно, я считаю. Нужно подключить несколько фреймворков, зафигачить с десяток микросервисов, общающихся через REST, утащить это всё в облако, подключить CDN… Короче, тема не раскрыта.
0

Да, что-то пропустил. Но таким вот образом можно поставить в тупик неканоничным решением задачи.

+1

Если бы оно ещё давало целые числа…


factorial(2) // 1.9999574974296939
0
Да никаких проблем:
var factorial = n => Math.round(Math.sqrt(2 * Math.PI * n) * Math.pow((n / Math.E), n) * Math.exp(1 / (12 * n) - 1 / (360 * n * n * n)));
0
Так-так, а что мешает взять формулу Стирлинга за определение факториала нецелого числа?
Кроме, конечно, требования о непрерывности, которого у нас, впрочем, и нет.
0

(комментарий оставлен в рамках федеральной целевой программы "говорить классным людям, что они классные")


Эта статья, как и многие другие ваши статьи, восхитительно прекрасна. Пишите ещё, пожалуйста.

Only those users with full accounts are able to leave comments. , please.