不确定这里的问题是什么。我知道我的因子函数是正确的,因为我单独测试它。但计算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 :(得分:3)
您的代码中有很多错误:
long
存储浮点结果。使用double
n
但使用更大的值进行循环:n
在一段时间后变为负数:无限循环e = e + (1/calcFactorial(counter));
大部分时间都会向e
添加0,因为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);
}
此代码输出:
Expected e value: 2.7182818284590451
Calculated e value: 2.7182815255731922
注意:您被限制在n
的给定最大值,因为在此之后您会溢出long
。也许可以考虑使用long long
或unsigned long long
作为阶乘部分(即使你受到严格限制)。
答案 1 :(得分:1)
让 - 弗朗索瓦·法布尔很好地突出了你的形式错误,但目前还没有用整数计算直到最后的分区 - 当然,这必须用浮点数来完成。这个技巧可以通过一个名为binary splitting的方法完成,令我惊讶的是,它的原生双打非常好,只有一个十进制数字。它实现起来也非常简单(下面的代码在考虑易读性的情况下编写)。
#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);
}
它使用与您相同的算法,但不计算各个分数并将它们总结为浮点数,而是使用整数一次性完成所有操作,使得我们在末尾有一大部分类似于{{1的近似值}}。这个解释有点过于简单,请阅读链接的文章了解详细信息。