2011-09-29 58 views
0

我被這個問題困住了2天。有人能幫我理解邏輯嗎?有人可以用更好的邏輯寫這段代碼嗎?

我正在研究C++程序以獲得更好的算法。我現在正在研究Danielson-Lanczos算法來計算序列的FFT。

看着

mmax=2; 
while (n>mmax) { 
    istep = mmax<<1; 
    theta = -(2*M_PI/mmax); 
    wtemp = sin(0.5*theta); 
    wpr = -2.0*wtemp*wtemp; 
    wpi = sin(theta); 
    wr = 1.0; 
    wi = 0.0; 

    for (m=1; m < mmax; m += 2) { 
     for (i=m; i <= n; i += istep) { 
      j=i+mmax; 
      tempr = wr*data[j-1] - wi*data[j]; 
      tempi = wr * data[j] + wi*data[j-1]; 

      data[j-1] = data[i-1] - tempr; 
      data[j] = data[i] - tempi; 
      data[i-1] += tempr; 
      data[i] += tempi; 
     } 
     wtemp=wr; 
     wr += wr*wpr - wi*wpi; 
     wi += wi*wpr + wtemp*wpi; 
    } 
    mmax=istep; 
} 

來源:http://www.eetimes.com/design/signal-processing-dsp/4017495/A-Simple-and-Efficient-FFT-Implementation-in-C--Part-I

有什麼辦法來邏輯地寫代碼,使得整個for-loop部分被減少到只有4行代碼(或更好)?

+8

只是刪除在循環體;-) – thkala

+11

*新行*爲什麼你想減少*行數*?在任何意義上,較少的行並不一定意味着更好的代碼......您希望在哪些方面使代碼更好? – thkala

+1

@thkala:並使用逗號運算符! – Cascabel

回答

8

更好的縮進會有很長的路要走。我爲你解決了這個問題。此外,這似乎要求更好的變量位置。變量名稱對我來說不清楚,但這可能是因爲我不知道這個算法屬於哪個域。

通常,如果您想使複雜的代碼更容易理解,請確定子算法並將它們放入自己的(內聯)函數中。 (將代碼片段放到一個函數中有效地賦予它一個名稱,並使得變量進出代碼更加明顯。通常,這會使代碼更易於消化。)
我不確定這是必需的這段代碼,但。

只是濃縮但是,代碼不會使其更具可讀性。相反,它會讓它變得更加濃縮。

2
  1. 我不相信你能夠使它大大縮短。
  2. 如果此代碼縮短了很多,我猜測它會顯着降低可讀性。
  3. 由於邏輯相對清晰,行數並不重要—除非你打算在codegolf.stackexchange.com上使用它,這是一個你應該相信你的編譯器來幫助你的地方(因爲它會)
  4. 這讓我覺得不成熟的優化。
5

不是壓縮你的代碼。請?請好嗎?頂部有櫻桃?

除非你可以創建一個更好的算法,否則壓縮現有的一段代碼只會使它看起來像是直接離開Hell本身的門。沒有人能夠理解它。 即使在幾天後,您也無法理解。

即使編譯器可能會被所有分支弄糊塗以正確優化它。

如果你想提高性能,考慮以下因素:

  1. 過早的優化是萬惡之源。

  2. 先處理算法,然後處理代碼。

  3. 行計數可能與生成的可執行代碼的大小完全沒有關係。

  4. 編譯器不喜歡糾纏的代碼路徑和複雜的表達式。真的...

  5. 除非代碼是真的性能的關鍵,可讀性勝過一切其他

  6. 如果它性能至關重要,首先配置文件,然後開始優化。

4

您可以使用複數類來反映所涉及的數學。

代碼的很大一部分是由兩個複數乘法組成的。

您可以重寫代碼爲:

unsigned long mmax=2; 
while (n>mmax) 
{ 
    unsigned long istep = mmax<<1; 
    const complex wp = coef(mmax); 
    complex w(1. , 0.); 
    for (unsigned long m=1; m < mmax; m += 2) 
    { 
     for (unsigned long i=m; i <= n; i += istep) 
     { 
      j=i+mmax; 
      complex temp = w * complex(data[j-1] , data[j]); 
      complexref(data[j-1] , data[j]) = complex(data[i-1] , data[i]) - temp ; 
      complexref(data[i-1] , data[i]) += temp ; 
     } 
     w += w * wp ; 
    } 
    mmax=istep; 
} 

有了:

struct complex 
{ 
    double r , i ; 
    complex(double r , double i) : r(r) , i(i) {} 

    inline complex & operator+=(complex const& ref) 
    { 
     r += ref.r ; 
     i += ref.i ; 
     return *this ; 
    } 
}; 

struct complexref 
{ 
    double & r , & i ; 
    complexref(double & r , double & i) : r(r) , i(i) {} 

    inline complexref & operator=(complex const& ref) 
    { 
     r = ref.r ; 
     i = ref.i ; 
     return *this ; 
    } 

    inline complexref & operator+=(complex const& ref) 
    { 
     r += ref.r ; 
     i += ref.i ; 
     return *this ; 
    } 
} ; 

inline complex operator*(complex const& w , complex const& b) 
{ 
    return complex(
     w.r * b.r - w.i * b.i , 
     w.r * b.i + w.i * b.r 
    ); 
} 

inline complex operator-(complex const& w , complex const& b) 
{ 
    return complex(w.r - b.r , w.i - b.i); 
} 
inline complex coef(unsigned long mmax) 
{ 
    double theta = -(2*M_PI/mmax); 
    double wtemp = sin(0.5*theta); 
    return complex(-2.0*wtemp*wtemp , sin(theta)); 
} 
+0

「通過添加大量可在此處一次性使用的代碼來縮短它的縮短時間?」 – cwallenpoole

+0

打算讓複數出現這樣,而不是整體更短。 fft代碼部分較短,而複雜的代碼應該由外部庫提供。 –

相關問題