creating a Sin formula in the c programming language
Hello everyone I'm trying to implement a programm like the fomular sin
The program will compile but when running it i am not getting the correct values back from my inputs. I'm still getting a negativ value.
can someone help me please ? I had a look at the other posts but that didn't help me :(.
my code is:
#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;
}
c visual-c++ sin
|
show 9 more comments
Hello everyone I'm trying to implement a programm like the fomular sin
The program will compile but when running it i am not getting the correct values back from my inputs. I'm still getting a negativ value.
can someone help me please ? I had a look at the other posts but that didn't help me :(.
my code is:
#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;
}
c visual-c++ sin
Yourpower_func
is not correct. It computesy^(2^x)
.
– lurker
Nov 20 '18 at 20:54
@lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result
– Amerov
Nov 20 '18 at 20:58
See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.
– lurker
Nov 20 '18 at 20:59
ohh mmm it's ok @lurker
– Amerov
Nov 20 '18 at 21:04
1
More specifically,y = y*y
is a problem...
– lurker
Nov 20 '18 at 21:07
|
show 9 more comments
Hello everyone I'm trying to implement a programm like the fomular sin
The program will compile but when running it i am not getting the correct values back from my inputs. I'm still getting a negativ value.
can someone help me please ? I had a look at the other posts but that didn't help me :(.
my code is:
#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;
}
c visual-c++ sin
Hello everyone I'm trying to implement a programm like the fomular sin
The program will compile but when running it i am not getting the correct values back from my inputs. I'm still getting a negativ value.
can someone help me please ? I had a look at the other posts but that didn't help me :(.
my code is:
#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;
}
c visual-c++ sin
c visual-c++ sin
edited Nov 20 '18 at 21:19
Amerov
asked Nov 20 '18 at 20:51
AmerovAmerov
397
397
Yourpower_func
is not correct. It computesy^(2^x)
.
– lurker
Nov 20 '18 at 20:54
@lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result
– Amerov
Nov 20 '18 at 20:58
See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.
– lurker
Nov 20 '18 at 20:59
ohh mmm it's ok @lurker
– Amerov
Nov 20 '18 at 21:04
1
More specifically,y = y*y
is a problem...
– lurker
Nov 20 '18 at 21:07
|
show 9 more comments
Yourpower_func
is not correct. It computesy^(2^x)
.
– lurker
Nov 20 '18 at 20:54
@lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result
– Amerov
Nov 20 '18 at 20:58
See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.
– lurker
Nov 20 '18 at 20:59
ohh mmm it's ok @lurker
– Amerov
Nov 20 '18 at 21:04
1
More specifically,y = y*y
is a problem...
– lurker
Nov 20 '18 at 21:07
Your
power_func
is not correct. It computes y^(2^x)
.– lurker
Nov 20 '18 at 20:54
Your
power_func
is not correct. It computes y^(2^x)
.– lurker
Nov 20 '18 at 20:54
@lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result
– Amerov
Nov 20 '18 at 20:58
@lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result
– Amerov
Nov 20 '18 at 20:58
See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.
– lurker
Nov 20 '18 at 20:59
See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.
– lurker
Nov 20 '18 at 20:59
ohh mmm it's ok @lurker
– Amerov
Nov 20 '18 at 21:04
ohh mmm it's ok @lurker
– Amerov
Nov 20 '18 at 21:04
1
1
More specifically,
y = y*y
is a problem...– lurker
Nov 20 '18 at 21:07
More specifically,
y = y*y
is a problem...– lurker
Nov 20 '18 at 21:07
|
show 9 more comments
1 Answer
1
active
oldest
votes
You have various misconceptions about your code. First, let's look at the formula you have provided:
sin(x) = sum((−1)^k * x^(2*k + 1) / (2*k + 1)! for x ∈ R; k = 0, ..., infinity
The sine function takes a real and returns a real. Therefore, you should use a floating-point type for x and sin(x). Use a double
. Let's also write a function that emulates sin
from <math.h>
:
double my_sin(double x);
The above series is accurate when there are infinitely many terms. We can't calculate that many, of course, and it would be a waste of time, too, because the terms are getting ever smaller until they can no longer be represented by a double
. So let's chose a maximum number of terms, say
enum {
nTerms = 8
};
Factorials grow big fast. A regular 32-bit int can hold 12! = 479,001,600. A 64-bit int can hold 20! = 2,432,902,008,176,640,000. Since we are going to use these factorials in a double
calculation, we can just as well use double
here. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.
Your power function should also have a double
base. The exponent is integer. (But please use the more natural order power(base, exp)
.
Finally, (−1)^k
is just an alternating sign. It is positive when k
is even and odd otherwise.
Putting all this together:
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;
}
If we write a driver program to print out some test values and compare them with the standard math library's implementation of 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%16gn", x, m, s, m - s);
}
return 0;
}
we can see that we're not doing so badly:
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
(But it gets worse the farther we go from zero. Try other values for nTerms
.)
I've said in a comment above that you don't need to calculate factorials and powers and that's true. If you look at the terms of the series, you will see that:
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] = ...
Here's a function that implements that.It calculates terms until adding them to the sum doesn't change it, because they are too small:
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;
}
The addition still loses some precision by summing the first terms first, but it has the benefit that it doesn't have to calculate factorials and powers. You don't even need <math.h>
.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401328%2fcreating-a-sin-formula-in-the-c-programming-language%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You have various misconceptions about your code. First, let's look at the formula you have provided:
sin(x) = sum((−1)^k * x^(2*k + 1) / (2*k + 1)! for x ∈ R; k = 0, ..., infinity
The sine function takes a real and returns a real. Therefore, you should use a floating-point type for x and sin(x). Use a double
. Let's also write a function that emulates sin
from <math.h>
:
double my_sin(double x);
The above series is accurate when there are infinitely many terms. We can't calculate that many, of course, and it would be a waste of time, too, because the terms are getting ever smaller until they can no longer be represented by a double
. So let's chose a maximum number of terms, say
enum {
nTerms = 8
};
Factorials grow big fast. A regular 32-bit int can hold 12! = 479,001,600. A 64-bit int can hold 20! = 2,432,902,008,176,640,000. Since we are going to use these factorials in a double
calculation, we can just as well use double
here. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.
Your power function should also have a double
base. The exponent is integer. (But please use the more natural order power(base, exp)
.
Finally, (−1)^k
is just an alternating sign. It is positive when k
is even and odd otherwise.
Putting all this together:
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;
}
If we write a driver program to print out some test values and compare them with the standard math library's implementation of 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%16gn", x, m, s, m - s);
}
return 0;
}
we can see that we're not doing so badly:
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
(But it gets worse the farther we go from zero. Try other values for nTerms
.)
I've said in a comment above that you don't need to calculate factorials and powers and that's true. If you look at the terms of the series, you will see that:
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] = ...
Here's a function that implements that.It calculates terms until adding them to the sum doesn't change it, because they are too small:
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;
}
The addition still loses some precision by summing the first terms first, but it has the benefit that it doesn't have to calculate factorials and powers. You don't even need <math.h>
.
add a comment |
You have various misconceptions about your code. First, let's look at the formula you have provided:
sin(x) = sum((−1)^k * x^(2*k + 1) / (2*k + 1)! for x ∈ R; k = 0, ..., infinity
The sine function takes a real and returns a real. Therefore, you should use a floating-point type for x and sin(x). Use a double
. Let's also write a function that emulates sin
from <math.h>
:
double my_sin(double x);
The above series is accurate when there are infinitely many terms. We can't calculate that many, of course, and it would be a waste of time, too, because the terms are getting ever smaller until they can no longer be represented by a double
. So let's chose a maximum number of terms, say
enum {
nTerms = 8
};
Factorials grow big fast. A regular 32-bit int can hold 12! = 479,001,600. A 64-bit int can hold 20! = 2,432,902,008,176,640,000. Since we are going to use these factorials in a double
calculation, we can just as well use double
here. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.
Your power function should also have a double
base. The exponent is integer. (But please use the more natural order power(base, exp)
.
Finally, (−1)^k
is just an alternating sign. It is positive when k
is even and odd otherwise.
Putting all this together:
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;
}
If we write a driver program to print out some test values and compare them with the standard math library's implementation of 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%16gn", x, m, s, m - s);
}
return 0;
}
we can see that we're not doing so badly:
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
(But it gets worse the farther we go from zero. Try other values for nTerms
.)
I've said in a comment above that you don't need to calculate factorials and powers and that's true. If you look at the terms of the series, you will see that:
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] = ...
Here's a function that implements that.It calculates terms until adding them to the sum doesn't change it, because they are too small:
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;
}
The addition still loses some precision by summing the first terms first, but it has the benefit that it doesn't have to calculate factorials and powers. You don't even need <math.h>
.
add a comment |
You have various misconceptions about your code. First, let's look at the formula you have provided:
sin(x) = sum((−1)^k * x^(2*k + 1) / (2*k + 1)! for x ∈ R; k = 0, ..., infinity
The sine function takes a real and returns a real. Therefore, you should use a floating-point type for x and sin(x). Use a double
. Let's also write a function that emulates sin
from <math.h>
:
double my_sin(double x);
The above series is accurate when there are infinitely many terms. We can't calculate that many, of course, and it would be a waste of time, too, because the terms are getting ever smaller until they can no longer be represented by a double
. So let's chose a maximum number of terms, say
enum {
nTerms = 8
};
Factorials grow big fast. A regular 32-bit int can hold 12! = 479,001,600. A 64-bit int can hold 20! = 2,432,902,008,176,640,000. Since we are going to use these factorials in a double
calculation, we can just as well use double
here. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.
Your power function should also have a double
base. The exponent is integer. (But please use the more natural order power(base, exp)
.
Finally, (−1)^k
is just an alternating sign. It is positive when k
is even and odd otherwise.
Putting all this together:
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;
}
If we write a driver program to print out some test values and compare them with the standard math library's implementation of 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%16gn", x, m, s, m - s);
}
return 0;
}
we can see that we're not doing so badly:
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
(But it gets worse the farther we go from zero. Try other values for nTerms
.)
I've said in a comment above that you don't need to calculate factorials and powers and that's true. If you look at the terms of the series, you will see that:
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] = ...
Here's a function that implements that.It calculates terms until adding them to the sum doesn't change it, because they are too small:
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;
}
The addition still loses some precision by summing the first terms first, but it has the benefit that it doesn't have to calculate factorials and powers. You don't even need <math.h>
.
You have various misconceptions about your code. First, let's look at the formula you have provided:
sin(x) = sum((−1)^k * x^(2*k + 1) / (2*k + 1)! for x ∈ R; k = 0, ..., infinity
The sine function takes a real and returns a real. Therefore, you should use a floating-point type for x and sin(x). Use a double
. Let's also write a function that emulates sin
from <math.h>
:
double my_sin(double x);
The above series is accurate when there are infinitely many terms. We can't calculate that many, of course, and it would be a waste of time, too, because the terms are getting ever smaller until they can no longer be represented by a double
. So let's chose a maximum number of terms, say
enum {
nTerms = 8
};
Factorials grow big fast. A regular 32-bit int can hold 12! = 479,001,600. A 64-bit int can hold 20! = 2,432,902,008,176,640,000. Since we are going to use these factorials in a double
calculation, we can just as well use double
here. That will even allow us to represent 22! = 1,124,000,727,777,607,680,000 accurately.
Your power function should also have a double
base. The exponent is integer. (But please use the more natural order power(base, exp)
.
Finally, (−1)^k
is just an alternating sign. It is positive when k
is even and odd otherwise.
Putting all this together:
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;
}
If we write a driver program to print out some test values and compare them with the standard math library's implementation of 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%16gn", x, m, s, m - s);
}
return 0;
}
we can see that we're not doing so badly:
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
(But it gets worse the farther we go from zero. Try other values for nTerms
.)
I've said in a comment above that you don't need to calculate factorials and powers and that's true. If you look at the terms of the series, you will see that:
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] = ...
Here's a function that implements that.It calculates terms until adding them to the sum doesn't change it, because they are too small:
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;
}
The addition still loses some precision by summing the first terms first, but it has the benefit that it doesn't have to calculate factorials and powers. You don't even need <math.h>
.
answered Nov 21 '18 at 10:00
M OehmM Oehm
21.4k31832
21.4k31832
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53401328%2fcreating-a-sin-formula-in-the-c-programming-language%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Your
power_func
is not correct. It computesy^(2^x)
.– lurker
Nov 20 '18 at 20:54
@lurker I have changed this line to num= power_func(x, 2*i+1); but I still get a wong answer like : Enter the number of x 3( ,-1.000000 ,1092.000000 ,4347.000000) the result
– Amerov
Nov 20 '18 at 20:58
See my initial comment about it being incorrectly calculated. Sorry, I was mistaken about the backward part.
– lurker
Nov 20 '18 at 20:59
ohh mmm it's ok @lurker
– Amerov
Nov 20 '18 at 21:04
1
More specifically,
y = y*y
is a problem...– lurker
Nov 20 '18 at 21:07