gpt4 book ai didi

c - 我应该如何处理返回错误答案的函数?

转载 作者:行者123 更新时间:2023-11-30 14:34:40 26 4
gpt4 key购买 nike

我们无法使用 math.h

如果我的正弦函数中的输入大于 54,而我的 exp 函数中的输入大于 37,我会得到错误的答案;我猜它溢出了,我该怎么办?我想自己编写正弦函数和exp函数,并使用泰勒展开式。我只需要分数中的 6 位数字;

    //Start of exp function
float exp(float x)
{
double expreturn=0;
long long int fctrl=1;
for(int n=0;n<=12;n++){

fctrl=1;
for(int i=2;i<=n;i++)
fctrl *= i;
expreturn += (pow(x,n)/fctrl);

}

return (float)expreturn;
}//End of exp function



//Start of sin function
float sin(float x)
{
double sinus=0;
long long int fctrl=1;
while(!(0<=x&&x<6.3))
{
if(x<0)
x += PI*2;
else
x -= PI*2;

}
for(int n=0;n<=8;n++)
{
fctrl=1;
for(int i=2;i<=(2*n+1);i++)
fctrl *= i;
sinus += ((pow(-1,n)*pow(x,2*n+1))/fctrl);
}
return (float)sinus;
}//End of sin function


//Start of pow function
float pow(float x,int y)
{
double pow = 1;
for(int i=0;i<y;i++)
pow *= x;
return (float)pow;
}//End of pow Function

以下是一些示例:

输入

sin(200)

所需输出

-0.873297

我的函数输出

-0.872985

但它可以在较小的值下正常工作

我用这个:

Here is my method

我现在能做什么?

最佳答案

sin() 中计算“x modulus 2 PI”的方式不会产生准确的结果,例如使用 x = 200 得到 5.221206,而 fmod() 返回 5.221255。

x 设为 double 而不是 float 为我解决了这个不准确问题。

这是我测试过的代码。它在没有优化的情况下或在 gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0

上使用 -O3 产生了相同的结果
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define PI 3.14159265358979323846264338

int main( int argc, char *argv[] )
{
double v = strtod( argv[1], 0 );
float f;
double d;

f = v;
while( f > 6.3 ) {
f -= 2*PI;
}

d = v;
while( d > 6.3 ) {
d -= 2*PI;
}

printf( "%f\n", f );
printf( "%lf\n", d );
printf( "%lf\n", fmod( v, 2*PI ) );
return( 0 );
}

编辑

正如 @Eric Postpischil@ 所指出的,这仍然不能解释错误的结果,所以“我已经开始玩弄 sin() 本身,并且似乎增加迭代次数可以提高准确性。将 fctrl 设为 unsigned long long,您可以迭代到 n=10 而不会溢出,对于 x=200 或 x=5.221255,您现在将得到结果 -0.873260这至少更接近。

这就是实际的代码:

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

#define PI 3.14159265358979323846264338

int iter = 8;
//Start of sin function
float mysin(double x)
{
double sinus=0;
unsigned long long int fctrl=1;
while(!(0<=x&&x<6.3))
{
if(x<0)
x += PI*2;
else
x -= PI*2;

}
for(int n=0;n<=iter;n++)
{
fctrl=1;
for(int i=2;i<=(2*n+1);i++)
fctrl *= i;

double pr = (pow(-1,n)*pow(x,2*n+1));
printf( "%lf / %llu\n", pr, fctrl );
sinus += pr / fctrl;
}
return (float)sinus;
}//End of sin function

int main( int argc, char *argv[] )
{
double v = strtod( argv[1], 0 );
if( argc > 2 ) {
iter = strtol( argv[2], 0, 10 );
}
float f;
double d;

f = v;
while( f > 6.3 ) {
f -= 2*PI;
}

d = v;
while( d > 6.3 ) {
d -= 2*PI;
}

/*
printf( "%f\n", f );
printf( "%lf\n", d );
printf( "%lf\n", fmod( v, 2*PI ) );
*/

printf( "%f\n", mysin( v ) );
return( 0 );
}

编辑2

另一个改进是避免计算 x ^ (2n+1) 和 n!首先(这将产生巨大的值),然后除法,但使用这样的循环:

for(int n=0;n<=iter;n++)
{
double v = n % 2 == 0 ? 1.0 : -1.0;
for( int j=1; j <= 2*n+1; j++ ) {
v *= x;
v /= j;
}
sinus += v;
}

当 n=10 时,mysin(200) 现在返回 -0.873296

关于c - 我应该如何处理返回错误答案的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58878242/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com