2017-02-06 1 views
-2

ここで何が問題なのかよくわかりません。私は別にそれをテストしたので、階乗関数が正しいことがわかります。しかし、eを計算する関数が私を引き上げています。私がしなければならないことは、各階乗が計算された後にすべての値を加算することだけです。しかし、私はそれをCコードに翻訳するのに問題があります。問題は私の2番目の機能です。どのような助けや指針をいただければ幸いです。定数の計算値を取得しないe

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

#define NOERROR 0 
#define DECIMAL_PLACES 16 
#define EXPECTED_E 2.7182818284590452L 

long calcFactorial(int); 
double calcE(int); 

long calcFactorial(int n) 
{ 
    long sum = 0; 
    sum = n; 

    if(n == 0) 
    { 
     return 1; 
    } 
    else 
    { 
     while(n != 1) 
     { 
      sum = sum * (n - 1); 
      n = n - 1; 
     } 
     printf("factorial sum: %ld\n", sum); 
     return sum; 
    } 
} 

double calcE(int n) 
{ 
    double e = 0; 
    int counter = 0; 

    for (counter = 0; counter < DECIMAL_PLACES; counter++) 
    { 
     e = e + (1/calcFactorial(n)); 
     n--; 
    } 

    printf("Expected e value: %0.16Lf\n", EXPECTED_E); 
    printf("Calculated e value: %0.16d\n", e); 

    return e; 
} 

int main() 
{ 
    calcE(10); 
} 
+1

なぜ 'calcE'は' long'を返すのですか? –

+2

'1/calcFactorial(n)'は整数除算のため常に0です。 これを変更することができます: '1.0/calcFactorial(n)' –

+0

@EliSadoff権利は、ダブル、またはおそらくは長いダブルでなければなりません。 –

答えて

3

あなたはあなたのコード内のエラーがたくさんある:浮動小数点の結果を格納するlongを使用して

  • double
  • nを渡すことが、より大きな値を使用してループを使用しますnはしばらくマイナスになる:calcFactorial戻っ整数(long
  • EXPECTED_E定数はLがあったので、無限ループ
  • e = e + (1/calcFactorial(counter));eにほとんどの時間を0を追加します接尾辞は、longを意味します。あなたが望むものではありません。

固定バージョン:

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

#define NOERROR 0 
#define DECIMAL_PLACES 16 
#define EXPECTED_E 2.7182818284590452 

long calcFactorial(int); 
void calcE(int); 

long calcFactorial(int n) 
{ 
    long sum = 0; 
    sum = n; 

    if(n == 0) 
    { 
     return 1; 
    } 
    else 
    { 
     while(n != 1) 
     { 
      sum *= (n - 1); 
      n = n - 1; 
     } 
    return sum; 
    } 
} 

void calcE(int n) 
{ 
    double e = 0; 
    int counter = 0; 

    for (counter = 0; counter < n; counter++) 
    { 
     e = e + (1.0/calcFactorial(counter)); 
    } 

    printf("Expected e value: %0.16lf\n", EXPECTED_E); 
    printf("Calculated e value: %0.16lf\n", e); 
} 

int main() 
{ 
    calcE(10); 
} 

このコード出力:

Expected e value: 2.7182818284590451 
Calculated e value: 2.7182815255731922 

注:後、あなたがlongをオーバーフローだろうとするので、あなたはnのために与えられた最大値に制限されています。階乗部分にはlong longまたはunsigned long longを使用することを検討してください(それでも、あなたは厳しく制限されています)。

1

ジャン=フランソワ・ファーブルは非常によくあなたの正式なエラーを強調したが、最終的な分裂までの整数で計算することが、これまでにフェッチではありません - もちろん、山車を行う必要があります。このトリックは、binary splittingというメソッドで行うことができます。私の驚いたことに、それは非常によくネイティブな倍精度で動作し、10進数は1桁だけオフになります。また、実装するのも非常に簡単です(以下のコードは読みやすいように書かれています)。

#include <stdio.h> 
#include <stdlib.h> 
#include <stdint.h> 

#define BS_AFU 0 
#define BS_AOK 1 

static int exp1_bin_split(uint64_t a, uint64_t b, uint64_t *P, uint64_t *Q){ 
    int err = BS_AOK; 

    uint64_t p1, q1, p2, q2, t1, one; 
    one = 1UL; 

    t1 = b - a; 
    if(t1 == one){ 
    *P = one; 
    *Q = b; 
    return err; 
    } 
    t1 = (a + b) >> 1; 

    err = exp1_bin_split(a, t1, &p1, &q1); 
    if(err != BS_AOK){ 
    return err; 
    } 
    err = exp1_bin_split(t1, b, &p2, &q2); 
    if(err != BS_AOK){ 
    return err; 
    } 

    *P = q2 * p1 + p2; 
    *Q = q1 * q2; 

    return err; 
} 

#include <float.h> 

static int exp1(double *a){ 
    int err = BS_AOK; 
    uint64_t p = 0UL, q = 0UL, zero = 0UL; 
    double dp, dq; 

    // DBL_DIG + 2 = 17 here on my machine 
    // had DBL_DIG + 1 first but found out via T&E that 
    // one more is still inside the precision of a binary64 
    err = exp1_bin_split(zero, DBL_DIG + 2, &p, &q); 
    if(err != BS_AOK){ 
    return err; 
    } 

    p = p + q; 

    dp = (double) p; 
    dq = (double) q; 

    *a = dp/dq; 

    return err; 
} 


int main(void){ 
    double e = 0.0; 
    int err = BS_AOK; 

    err = exp1(&e); 
    if(err != BS_AOK){ 
    fprintf(stderr,"Something went wrong in computing e\n"); 
    exit(EXIT_FAILURE); 
    } 

    printf("exp(1) ~ 2.7182818284590452353602874713526624978\nexp1 ~ %.20g\n",e); 

    exit(EXIT_SUCCESS); 
} 

それはあなたが行うのと同じアルゴリズムを使用していますが、個々の画分を計算しないと山車として、それらを合計するが、我々は近似に似ていると最後に大部分を有するように整数で一度にすべてを行いますexp(1)です。その説明はちょっと単純すぎます。詳細についてはリンク先の論文をお読みください。

関連する問題