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