首頁  >  文章  >  後端開發  >  python中的迭代與遞歸

python中的迭代與遞歸

高洛峰
高洛峰原創
2016-10-19 11:56:201265瀏覽

遇到一個情況,需要進行遞歸操作,但是呢遞歸次數非常大,有一萬多次。先不說一萬多次遞歸,原來的測試程式碼是java的,沒裝jdk和編譯環境,還是用python吧

先看下原本的java程式碼:

public class UpCount {
    private long calc(int depth) {
        if (depth == 0) return 1;
        long cc = calc(depth - 1);
        return cc + (depth % 7) + ((((cc ^ depth) % 4) == 0) ? 1 : 0); 
    }
    public static void main(String[] args) {
        UpCount uc = new UpCount();
        System.out.println(uc.calc(11589));
    }
}

   

java沒怎麼玩過,但是這幾行程式碼看過來還是沒壓力的,快刀斬亂麻改為對於python代碼

def calc(depth):
    if depth == 0:
        return 1
    cc = long(calc(depth-1))
    xor_mod = (cc ^ depth)%4
    if xor_mod == 0:
        return cc+(depth%7)+1
    else:
        return cc+(depth%7)
  
number = long(calc(11589))
print number

   

代碼粘上去,F5,出錯了

代碼粘上去,F5,出錯了

這個版本的代碼本來是沒有加long因為之前一串十幾位的整數直接拿來就可以用,所以懷疑跟long是不是有關係

當然啦,事實上這裡跟long完全沒關係,python支持的整數長度可是非常長的,參考之前寫的程式碼如下:

cimal = 7
original = 28679718602997181072337614380936720482949
array = ""
result= ""
while original !=0:
    remainder = original % cimal
    array += str(remainder)
    original /= cimal
length = len(array)
for i in xrange(0,length):
    result += array[length-1-i]
print result

   

上面這段程式碼將一串很長的十進位數字轉為7進位表示,也可以轉為任意進位,換做是8進位和16進位,一個oct(),hex()就搞定了,用輾轉相除法來解決吧

因此,可以看出來,出錯不在於數的大小,畢竟11589對現在的計算機來說只是小菜,2^16還有65536呢

其實到這裡才發現,沒有說前面遞歸報錯的真正原因,憔悴了

遞歸出錯的原因是因為python默認的遞歸限制只有1000次左右,但是這裡卻要運行10000+,刷了半天:RuntimeError: maximum recursion depth exceeded

於是趕緊查了下,發現可以自己設定遞歸的限制,見python中遞歸的最大次數,作為延伸也可以查看官網文檔

總的說來就是,為了防止益處和崩潰,python語言預設對次數加了限制,那麼我改了這個限制是不是就ok了呢

import sys

# set the maximun depth as 20000

sys.setrecursionlimit(20000)

,20000果斷改20000,這下沒這限制應該沒問題了,但是結果卻大跌眼鏡,什麼都沒輸出來,不解了

沒有繼續查了,問了下小伙伴littlehann,討論了下, 沒有對這個問題深究下去。而是提到遞歸這種運算在實際應用上的效率,確實除了課本上很少看到使用遞歸的

本來的目的就只是求值,沒想對它深究下去,還是改用迭代吧,雖然沒太大印象了,不過一個for語句據可以搞定了


程式碼如下:

def calc(depth):
    tmp = 0
    result = 1
     
    for i in xrange(0,depth+1):
        cc = result
        if (cc ^ i)%4 == 0:
            tmp = 1
        else:
            tmp = 0
        result = result + (i)%7 + tmp
         
    return result
final = calc(11589)
print final

   


短短幾行程式碼,一下子搞定了。想到上次面試的時候,tx的面試官問我演算法,當時提到了用遞歸實作一個運算,再想想是不是也可以用迭代呢?

時間過去很久了,當時的題目也記不太清楚了,但是今天的教訓是:大多數(代碼寫得少,憑感覺說的估計值)情況下,遞歸的效率是比較低下的,這一點可以確定,上課的

時候也有講過。使用迭代的效率明顯要高過遞歸(迭代的具體概念記不太清楚了),起碼用循環,運算幾十萬次我可以肯定沒問題,但是即便我改了遞歸限制,還是遇到了罷工


最後,再貼出一個python long VS C long long的鏈接,有興趣的可以去看看

🎜🎜🎜
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn