C 没有得到常数e的计算值

C 没有得到常数e的计算值,c,C,我不太确定这里有什么问题。我知道我的阶乘函数是正确的,因为我单独测试了它。但是计算e的函数让我大吃一惊。我所要做的就是在计算每个阶乘之后添加所有的值。但是我很难把它翻译成C代码。问题肯定出在我的第二个函数中。任何帮助或指点都将不胜感激 #include <stdio.h> #include <math.h> #define NOERROR 0 #define DECIMAL_PLACES 16 #define EXPECTED_E 2.7182818284590452L

我不太确定这里有什么问题。我知道我的阶乘函数是正确的,因为我单独测试了它。但是计算e的函数让我大吃一惊。我所要做的就是在计算每个阶乘之后添加所有的值。但是我很难把它翻译成C代码。问题肯定出在我的第二个函数中。任何帮助或指点都将不胜感激

#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);
}
#包括
#包括
#定义无错误0
#定义小数点后16位
#定义预期值2.7182818284590452L
长计算器(int);
双计算(int);
长计算器(int n)
{
长和=0;
总和=n;
如果(n==0)
{
返回1;
}
其他的
{
而(n!=1)
{
总和=总和*(n-1);
n=n-1;
}
printf(“阶乘和:%ld\n”,和);
回报金额;
}
}
双计算(整数n)
{
双e=0;
int计数器=0;
用于(计数器=0;计数器<小数点;计数器++)
{
e=e+(1/计算因子(n));
n--;
} 
printf(“预期e值:%0.16Lf\n”,预期e);
printf(“计算的e值:%0.16d\n”,e);
返回e;
}
int main()
{
calcE(10);
}

您的代码中有很多错误:

  • 使用
    long
    存储浮点结果。使用
    double
  • 传递
    n
    但使用较大的值循环:
    n
    一段时间后变为负值:无限循环
  • e=e+(1/计算器(计数器))在大多数情况下将0添加到
    e
    ,因为
    calcFactorial
    返回一个整数(
    long
  • EXPECTED_E
    常量有
    L
    后缀,表示
    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);
}

注意:
n
限制为给定的最大值,因为在此之后将溢出
long
。也许考虑使用<代码>长long < /代码>或<代码>未署名的long long //CODE >阶乘部分(即使是你受到严格限制)。弗兰·S. O.FiRe强调了你的形式错误,但是用整数来计算最终的划分并不是那么牵强,当然必须用浮标来计算。这个技巧可以通过一个名为的方法来实现,令我惊讶的是,它可以很好地实现本地双精度,只差一个十进制数字。它的实现也非常简单(下面的代码编写时考虑到易读性)

#包括
#包括
#包括
#定义BS_AFU 0
#定义BS_AOK 1
静态int exp1_bin_分割(uint64_t a、uint64_t b、uint64_t*P、uint64_t*Q){
int err=BS_AOK;
uint64_t p1,q1,p2,q2,t1,一;
一个=1UL;
t1=b-a;
如果(t1==1){
*P=1;
*Q=b;
返回错误;
}
t1=(a+b)>>1;
err=exp1\u bin\u分割(a、t1、p1和q1);
如果(错误!=b_AOK){
返回错误;
}
err=exp1\u bin\u分割(t1、b、p2和q2);
如果(错误!=b_AOK){
返回错误;
}
*P=q2*p1+p2;
*Q=q1*q2;
返回错误;
}
#包括
静态整数表达式1(双精度*a){
int err=BS_AOK;
uint64_t p=0UL,q=0UL,0=0UL;
双dp,dq;
//DBL_DIG+2=17在我的机器上
//先让DBL_挖掘+1,但通过T&E发现
//还有一个仍然在二进制64的精度范围内
err=exp1\u bin\u split(零,DBL\u DIG+2,&p,&q);
如果(错误!=b_AOK){
返回错误;
}
p=p+q;
dp=(双)p;
dq=(双)q;
*a=dp/dq;
返回错误;
}
内部主(空){
双e=0.0;
int err=BS_AOK;
err=exp1&e;
如果(错误!=b_AOK){
fprintf(stderr,“计算中出错了”\n);
退出(退出失败);
}
printf(“exp(1)~2.7182818284590453602874713526624978\nexp1~.20g\n”,e);
退出(退出成功);
}

它使用与您相同的算法,但不计算单个分数并将其作为浮点数求和,而是同时使用整数进行计算,这样我们在末尾有一个大分数,类似于
exp(1)
的近似值。该解释过于简化,请阅读链接文章了解详细信息。

为什么
calcE
long
返回?
1/calcFactorial(n)
由于整数除法始终为0。您可以将其更改为:
1.0/calcFactorial(n)
@EliSadoff对,这应该是一个双精度,甚至可能是一个长双精度。而且
calcE
甚至不返回任何内容请注意12!是适合32位整数的最大阶乘;20! 是适合64位整数的最大阶乘。
Expected e value: 2.7182818284590451
Calculated e value: 2.7182815255731922
#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);
}