2015-11-21 15 views
3

這裏我有一個小問題。從這個公式創造的東西:如何在C中使用連續分數實現自然對數​​?

enter image description here

這是我有什麼,但它不工作。弗蘭基,我真的不明白它應該如何工作..我試圖用一些不好的指示來編碼。 N是迭代次數和分數的一部分。我認爲這會導致遞歸,但不知道如何。

感謝您的任何幫助。

double contFragLog(double z, int n) 
{ 
    double cf = 2 * z; 
    double a, b; 
    for(int i = n; i >= 1; i--) 
    { 
     a = sq(i - 2) * sq(z); 
     b = i + i - 2; 
     cf = a/(b - cf); 

    } 
    return (1 + cf)/(1 - cf); 
} 
+1

我沒有檢查循環,但最終的結果計算是錯誤的。你不想返回'(1 + cf)/(1-cf)'。該公式計算'log((1 + z)/(1-z))'。所以如果你想要'log(x)',你必須弄清楚'z'的值是什麼給你'x =(1 + z)/(1-z)',然後按照'z'計算我假設你已經完成並且公式顯示)並按原樣返回結果。 – lurker

+1

循環公式看起來並不正確。不知何故,你需要一個'z * z'在那裏,但我沒有看到它。你有'b = i + i - 2'這與'b = 2 *(i - 1)'相同,因此你的'b'總是偶數(我在公式中看到一個奇數序列)。 – lurker

+0

您的持續分數與維基百科給出的分數不匹配(https://en.wikipedia.org/wiki/Euler%27s_continued_fraction_formula)。我無法確定它們是否真的不同,但是你確定你顯示的是正確的嗎? – MicroVirus

回答

2

中央環路混亂。返工。也不需要遞歸。只要先計算最深的術語,然後按照你的方式工作。

double contFragLog(double z, int n) { 
    double zz = z*z; 
    double cf = 1.0; // Important this is not 0 
    for (int i = n; i >= 1; i--) { 
    cf = (2*i -1) - i*i*zz/cf; 
    } 
    return 2*z/cf; 
} 

void testln(double z) { 
    double y = log((1+z)/(1-z)); 
    double y2 = contFragLog(z, 8); 
    printf("%e %e %e\n", z, y, y2); 
} 

int main() { 
    testln(0.2); 
    testln(0.5); 
    testln(0.8); 
    return 0; 
} 

輸出

2.000000e-01 4.054651e-01 4.054651e-01 
5.000000e-01 1.098612e+00 1.098612e+00 
8.000000e-01 2.197225e+00 2.196987e+00 

[編輯]

根據提示通過@MicroVirus,我發現double cf = 1.88*n - 0.95;工作比double cf = 1.0;更好。隨着更多條款的使用,使用的價值差異較小,但良好的初始cf需要更少的條款來獲得良好的答案,特別是對於接近0.5的|z|。當我研究0 < z <= 0.5時,可以在這裏完成更多的工作。由於n是錯誤的,因此微軟建議的2*n+1可能接近我的建議。

這是基於反向計算,並注意到值CF[n]n增加。我很驚訝「種子」的價值似乎並不是一些很好的整數方程。

+0

你是如何決定把'cf = 1.0'作爲開始的?我的第一個直覺就是'2 * n + 1',但我並沒有很好的理由,我真的很好奇什麼纔是正確的開始價值。 – MicroVirus

+0

遞歸不是必需的,但是對於這個問題來說這是一個很好的方法(因爲它看起來像按照您讀取的順序計算結果),如果計算遞歸之外的第一項,遞歸解決方案非常短。 –

+0

哦,真的很好。它工作得很好,謝謝!我在函數的開頭添加了z =(z - 1)/(z + 1,現在它完美了); – lamortheureuse

0

下面就來,做使用遞歸(如果有人有興趣)的問題的解決方案:

#include <math.h> 
#include <stdio.h> 

/* `i` is the iteration of the recursion and `n` is 
    just for testing when we should end. 'zz' is z^2 */ 
double recursion (double zz, int i, int n) { 
    if (!n) 
    return 1; 

    return 2 * i - 1 - i * i * zz/recursion (zz, i + 1, --n); 
} 

double contFragLog (double z, int n) { 
    return 2 * z/recursion (z * z, 1, n); 
} 

void testln(double z) { 
    double y = log((1+z)/(1-z)); 
    double y2 = contFragLog(z, 8); 
    printf("%e %e %e\n", z, y, y2); 
} 

int main() { 
    testln(0.2); 
    testln(0.5); 
    testln(0.8); 
    return 0; 
} 

輸出相同上述的解決:

2.000000e-01 4.054651e-01 4.054651e-01 
5.000000e-01 1.098612e+00 1.098612e+00 
8.000000e-01 2.197225e+00 2.196987e+00 
相關問題