用c编程语言创建一个Sin公式
creating a Sin formula in the c programming language
大家好,我正在尝试实现一个像公式 sin 这样的程序
该程序将编译,但是当 运行 它时,我没有从我的输入中得到正确的值。我仍然得到负值。
有谁可以帮助我吗 ?我看了其他帖子,但这对我没有帮助:(。
我的代码是:
#include <stdio.h>
#include <stdlib.h>
int fac (int a) { // fac. => factorial and i is for the loop
int i,fac;
fac=1;
for (i=1; i<=a; i++){
fac=fac*i;
}
return fac;
}
int power_func(int x,int y) // x is exponent and y is the number that would be multiplied by itself.
{
int i;//i is for the loop
int ret = 1;
for(i=1;i<=x;i++)
{
ret *= y;
}
return ret;
}
int main()
{
int num,denom,i;//num. is numerator and denom. is denominator
int sin,x,result=0;
printf("Enter the number of x \n");
scanf("%d",&x);
for(i=0;i<x;i++)
{
num= power_func(2*i+1,x);
denom=fac((2*i+1));
sin=power_func(i,-1)*num/denom;
result =result+sin;
printf("%d \n",result);
}
return 0;
}
您对您的代码有各种误解。首先,让我们看看您提供的公式:
sin(x) = sum((−1)^k * x^(2*k + 1) / (2*k + 1)! for x ∈ R; k = 0, ..., infinity
正弦函数取实数,returns取实数。因此,您应该为 x 和 sin(x) 使用浮点类型。使用 double
。让我们也写一个函数,从 <math.h>
:
模拟 sin
double my_sin(double x);
当有无穷多个项时,上述系列是准确的。当然,我们不能计算那么多,而且这也是浪费时间,因为项变得越来越小,直到它们不再可以用 double
表示。所以让我们选择最大数量的术语,比如
enum {
nTerms = 8
};
阶乘增长很快。一个普通的 32 位 int 可以容纳 12! = 479,001,600。一个 64 位的 int 可以容纳 20! = 2,432,902,008,176,640,000。由于我们将在 double
计算中使用这些阶乘,因此我们也可以在此处使用 double
。这甚至可以让我们代表 22! = 1,124,000,727,777,607,680,000 准确。
你的幂函数也应该有一个 double
基数。指数是整数。 (但请使用更自然的顺序 power(base, exp)
.
最后,(−1)^k
只是一个交替符号。当 k
为偶数时为正,否则为奇数。
将所有这些放在一起:
double fact(int n)
{
double result = 1.0;
while (n > 0) {
result *= n;
n--;
}
return result;
}
double power(double a, int n)
{
double result = 1.0;
while (n > 0) {
result *= a;
n--;
}
return result;
}
enum {
nTerms = 8
};
double my_sin(double x)
{
double result = 0.0;
double sign = 1.0;
for(int k = 0; k < nTerms; k++)
{
double num = power(x, 2*k + 1);
double denom = fact(2*k + 1);
double term = sign * num / denom;
result = result + term;
sign = -sign;
}
return result;
}
如果我们编写一个驱动程序来打印一些测试值,并将它们与标准数学库的实现进行比较 sin
:
int main(void)
{
for (int i = 0; i < 15; i++) {
double x = 0.1 * i;
double m = my_sin(x); // series approximation
double s = sin(x); // <math.h> implementation
printf("%16g%16g%16g%16g\n", x, m, s, m - s);
}
return 0;
}
我们可以看到我们做得还不错:
x my_sin(x) sin(x) difference
-------- ------------ ------------ ------------
0 0 0 0
0.1 0.0998334 0.0998334 1.38778e-17
0.2 0.198669 0.198669 2.77556e-17
0.3 0.29552 0.29552 0
0.4 0.389418 0.389418 -5.55112e-17
0.5 0.479426 0.479426 0
0.6 0.564642 0.564642 0
0.7 0.644218 0.644218 0
0.8 0.717356 0.717356 0
0.9 0.783327 0.783327 -4.44089e-16
1 0.841471 0.841471 -2.77556e-15
1.1 0.891207 0.891207 -1.43219e-14
1.2 0.932039 0.932039 -6.20615e-14
1.3 0.963558 0.963558 -2.42029e-13
1.4 0.98545 0.98545 -8.52318e-13
(但我们离零越远情况越糟。尝试 nTerms
的其他值。)
我在上面的评论中说过,您不需要计算阶乘和幂,这是事实。如果您查看该系列的条款,您会看到:
s[n] = -1 * s[n - 1] * x^2 / (2*n * (2*n +1))
s[0] = x
s[1] = x^3 / (1 * 2 * 3) = x * x^2 / (2 * 3)
s[2] = x^5 / (1 * 2 * 3 * 4 * 5) = x^3 / (1 * 2 * 3) * x^2 / (4 * 5)
s[3] = ...
这是一个实现 that.It 计算项的函数,直到将它们添加到总和中不会改变它,因为它们太小了:
double sin_r(double x)
{
double sum = x;
double a = x;
int n;
for (n = 1; ; n++) {
double was = sum;
a = -a * x*x / (2*n) / (2*n + 1);
sum += a;
if (was == sum) break;
}
return sum;
}
通过首先对第一项求和,加法仍然会损失一些精度,但它的好处是不必计算阶乘和幂。你甚至不需要 <math.h>
.
大家好,我正在尝试实现一个像公式 sin 这样的程序 该程序将编译,但是当 运行 它时,我没有从我的输入中得到正确的值。我仍然得到负值。 有谁可以帮助我吗 ?我看了其他帖子,但这对我没有帮助:(。 我的代码是:
#include <stdio.h>
#include <stdlib.h>
int fac (int a) { // fac. => factorial and i is for the loop
int i,fac;
fac=1;
for (i=1; i<=a; i++){
fac=fac*i;
}
return fac;
}
int power_func(int x,int y) // x is exponent and y is the number that would be multiplied by itself.
{
int i;//i is for the loop
int ret = 1;
for(i=1;i<=x;i++)
{
ret *= y;
}
return ret;
}
int main()
{
int num,denom,i;//num. is numerator and denom. is denominator
int sin,x,result=0;
printf("Enter the number of x \n");
scanf("%d",&x);
for(i=0;i<x;i++)
{
num= power_func(2*i+1,x);
denom=fac((2*i+1));
sin=power_func(i,-1)*num/denom;
result =result+sin;
printf("%d \n",result);
}
return 0;
}
您对您的代码有各种误解。首先,让我们看看您提供的公式:
sin(x) = sum((−1)^k * x^(2*k + 1) / (2*k + 1)! for x ∈ R; k = 0, ..., infinity
正弦函数取实数,returns取实数。因此,您应该为 x 和 sin(x) 使用浮点类型。使用 double
。让我们也写一个函数,从 <math.h>
:
sin
double my_sin(double x);
当有无穷多个项时,上述系列是准确的。当然,我们不能计算那么多,而且这也是浪费时间,因为项变得越来越小,直到它们不再可以用 double
表示。所以让我们选择最大数量的术语,比如
enum {
nTerms = 8
};
阶乘增长很快。一个普通的 32 位 int 可以容纳 12! = 479,001,600。一个 64 位的 int 可以容纳 20! = 2,432,902,008,176,640,000。由于我们将在 double
计算中使用这些阶乘,因此我们也可以在此处使用 double
。这甚至可以让我们代表 22! = 1,124,000,727,777,607,680,000 准确。
你的幂函数也应该有一个 double
基数。指数是整数。 (但请使用更自然的顺序 power(base, exp)
.
最后,(−1)^k
只是一个交替符号。当 k
为偶数时为正,否则为奇数。
将所有这些放在一起:
double fact(int n)
{
double result = 1.0;
while (n > 0) {
result *= n;
n--;
}
return result;
}
double power(double a, int n)
{
double result = 1.0;
while (n > 0) {
result *= a;
n--;
}
return result;
}
enum {
nTerms = 8
};
double my_sin(double x)
{
double result = 0.0;
double sign = 1.0;
for(int k = 0; k < nTerms; k++)
{
double num = power(x, 2*k + 1);
double denom = fact(2*k + 1);
double term = sign * num / denom;
result = result + term;
sign = -sign;
}
return result;
}
如果我们编写一个驱动程序来打印一些测试值,并将它们与标准数学库的实现进行比较 sin
:
int main(void)
{
for (int i = 0; i < 15; i++) {
double x = 0.1 * i;
double m = my_sin(x); // series approximation
double s = sin(x); // <math.h> implementation
printf("%16g%16g%16g%16g\n", x, m, s, m - s);
}
return 0;
}
我们可以看到我们做得还不错:
x my_sin(x) sin(x) difference
-------- ------------ ------------ ------------
0 0 0 0
0.1 0.0998334 0.0998334 1.38778e-17
0.2 0.198669 0.198669 2.77556e-17
0.3 0.29552 0.29552 0
0.4 0.389418 0.389418 -5.55112e-17
0.5 0.479426 0.479426 0
0.6 0.564642 0.564642 0
0.7 0.644218 0.644218 0
0.8 0.717356 0.717356 0
0.9 0.783327 0.783327 -4.44089e-16
1 0.841471 0.841471 -2.77556e-15
1.1 0.891207 0.891207 -1.43219e-14
1.2 0.932039 0.932039 -6.20615e-14
1.3 0.963558 0.963558 -2.42029e-13
1.4 0.98545 0.98545 -8.52318e-13
(但我们离零越远情况越糟。尝试 nTerms
的其他值。)
我在上面的评论中说过,您不需要计算阶乘和幂,这是事实。如果您查看该系列的条款,您会看到:
s[n] = -1 * s[n - 1] * x^2 / (2*n * (2*n +1))
s[0] = x
s[1] = x^3 / (1 * 2 * 3) = x * x^2 / (2 * 3)
s[2] = x^5 / (1 * 2 * 3 * 4 * 5) = x^3 / (1 * 2 * 3) * x^2 / (4 * 5)
s[3] = ...
这是一个实现 that.It 计算项的函数,直到将它们添加到总和中不会改变它,因为它们太小了:
double sin_r(double x)
{
double sum = x;
double a = x;
int n;
for (n = 1; ; n++) {
double was = sum;
a = -a * x*x / (2*n) / (2*n + 1);
sum += a;
if (was == sum) break;
}
return sum;
}
通过首先对第一项求和,加法仍然会损失一些精度,但它的好处是不必计算阶乘和幂。你甚至不需要 <math.h>
.