2017-08-04 127 views
2

我以這種方式使用while如何用遞歸函數替換?

while (value < -180 || value > 180) { 
    if (value < -180) { 
    value += 360 
    } 
    if (value > 180) { 
    value -= 360 
    } 
} 

我想,雖然,使用遞歸函數代替while。我在谷歌搜索,但不能find什麼。所以我想也許我可以在這裏得到答案。

+2

爲什麼使用遞歸?除非問題特別受益於遞歸解決方案,否則遞歸會阻礙您的程序。 – Carcigenicate

+0

@Carcigenicate我想避免使用'while'出於個人原因。 – alex

+0

我鼓勵你仔細考慮這些個人原因。每個工具都有它的位置。 – Carcigenicate

回答

2

「一般公式」爲一個顯式的環轉化爲一個遞歸的解決方案是:

  • 圖出了什麼環路的「累加器」是。通常,循環將操縱一個或兩個值,而這些值是循環的「結果」。

  • 使累加器成爲函數的參數。

這是很難一概而論如何任何舊線圈,可以用遞歸來代替,但是這可以作爲一般的指導原則:

爲了與形式的循環:

var a, b, c = ...; 

while (condition) { 
    // Change a, b, c... 
} 

// Use a, b, c 

你可以將其轉換爲:

function recursive(a, b, c...) { 
    // When the condition does *not* hold, end the recursion. 
    // Note that condition is negated relative to the while-loop. 
    if (!condition) { 
     // Base case. 
     return [a, b, c...]; 

    } else { 
     // Change a, b, c... 
     // and recurse with the new values 
     return recursive(a', b', c'...); 
    } 
} 

對於您的示例,這看起來像這樣:

function recur(value) { 
    if (value > -180 || value < 180) { 
    return value; // Base case 

    } else if (value < -180) { 
    return recur(value + 360); 

    } else { 
    return recur(value - 360); 
    } 
} 

在您希望再次循環,遞歸,案件但請記住,你需要返回遞歸的結果。對於要結束循環的情況,請返回累加器。請注意,執行的每個分支必須以的回報結束。一旦放棄遞歸的結果(通過不返回),數據就會丟失。

但是請注意:

  • 正如我在評論中提到的,遞歸是不應該在任何舊的問題被拋出的撞錘;特別是當語言未針對其進行優化時。對於小問題可能沒有問題,但在後面,當問題變得更大時,您可能會發現它突然開始導致StackOverflow無處可逃。

  • 當處理可變數據時,遞歸可能會變得困難和混亂。如果你的累加器是可變的(一個列表,地圖或任何其他非原始的),你必須非常小心你如何設置一切。可以從遞歸的每個分支訪問相同的數據並更改。如果你不小心,你會以非常難以調試的方式將你的累加器從你的下面改掉。如果你想進入遞歸/功能路徑,我鼓勵你去查看像Immutable.js這樣的庫,或者像Clojurescript這樣的語言,它幾乎完全處理不可變結構。 Clojurescript編譯成JavaScript。

+0

謝謝你的例子。但我想要一個遞歸函數,可以應用於任何可以使用的情況。不只是我的例子。 – alex

+1

@alex遞歸很難一般化,這就是爲什麼我在答案開始時列出這個列表。儘管我會盡力寫出一個廣義的「藍圖」。 – Carcigenicate

2

試試這個:

var recur_num = recursion(500) 
 
console.log(recur_num) 
 

 
var while_num = viaLoop(500) 
 
console.log(while_num) 
 

 
function recursion(value) { 
 
    
 
    if (value < -180) { 
 
    return recursion(value + 360); 
 
} 
 
    
 
    if(value > 180){ 
 
    return recursion(value - 360); 
 
    } 
 
    
 
    if (value > -180 || value < 180) { 
 
    return value; 
 
    } 
 
} 
 

 

 
function viaLoop(value){ 
 

 
while (value < -180 || value > 180) { 
 

 
if (value < -180) { 
 
    value += 360 
 
    } 
 
    
 
    if (value > 180) { 
 
    value -= 360 
 
    } 
 
} 
 

 
return value; 
 
}

您可以比較兩個版本的遞歸值和while循環版本值

+0

讓我知道你是否有任何疑慮? – dawit