階乘介紹:一個正整數的階乘是所有小於及等於該數的正整數的積,並且有0
的階乘為1
。自然數n
的階乘寫作n!
階乘函數是遞歸函數典型示例。
階乘的實現方法(一種遞歸,兩種循環):
方法1:遞歸
function factorial (num) {
if (num < 0) {
return -1;
} else if (num === 0 || num === 1) {
return 1;
} else {
return (num * factorial(num - 1));
}
};
factorial(6);
定義階乘函數一般都要用到遞歸算法;如上面的代碼所示,在函數有名字,而且名字以后也不會變的情況下,這樣定義沒有問題。但問題是這個函數的執行與函數名 factorial 緊緊耦合在了一起。為了消除這種緊密耦合的現象,可以像下面這樣使用 arguments.callee。(非嚴格模式)
function factorial(num){ if (num <=1) { return 1; } else { return num * arguments.callee(num-1) } }
在這個重寫后的factorial()函數的函數體內,沒有再引用函數名 factorial。這樣,無論引用函數時使用的是什么名字,都可以保證正常完成遞歸調用。
var trueFactorial = factorial; factorial = function(){ return 0; }; alert(trueFactorial(5)); //120 alert(factorial(5)); //0
但在嚴格模式下,不能通過腳本訪問 arguments.callee,訪問這個屬性會導致錯誤。不過,可以使用命名函數表達式來達成相同的結果
var factorial = (function f(num){ if (num <= 1){
return 1; } else {
return num * f(num-1);
}
});
方法2:for循環
function factorial (num) {
if (num < 0) {
return -1;
} else if (num === 0 || num === 1) {
return 1;
} else {
for (var i = num - 1; i >= 1; i--) {
num *= i;
}
}
return num;
};
factorial(6);
方法3:while循環
function factorial (num) {
var result = num;
if (num < 0) {
return -1;
} else if (num === 0 || num === 1) {
return 1;
} else {
while (num > 1) {
num--;
result *= num;
}
}
return result;
};
factorial(6);
方法4:尾遞歸
function factorial(n, total) { if (n === 1) return total; return factorial(n - 1, n * total); } factorial(5, 1) // 120