The sine function can be computed from scratch using its Taylor series expansion:
sin(x) = x − x³/3! + x⁵/5! − x⁷/7! + x⁹/9! − …
Each term alternates in sign and uses an odd power of x divided by the corresponding factorial. As you add more terms, the partial sum converges toward the true value of sin(x). This series expansion is the mathematical foundation behind how CPUs and math libraries compute trigonometric functions. The original post had no code; this is a complete C89 implementation with convergence comparison against math.h.
Term-by-Term Trace for sin(x=1, n=5 terms)
| Term # | Expression | Value | Running sum |
|---|---|---|---|
| 1 | x¹/1! = 1/1 | 1.000000 | 1.000000 |
| 2 | −x³/3! = −1/6 | −0.166667 | 0.833333 |
| 3 | x⁵/5! = 1/120 | 0.008333 | 0.841667 |
| 4 | −x⁷/7! = −1/5040 | −0.000198 | 0.841468 |
| 5 | x⁹/9! = 1/362880 | 0.000003 | 0.841471 |
True value: sin(1) = 0.841471 ✓ — 5 terms gives 6 significant figures.
C Program: sin(x) Taylor Series
/* Evaluate sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
* Compile: gcc -ansi -Wall -Wextra sintaylor.c -o sintaylor -lm */
#include <stdio.h>
#include <math.h>
int main(void)
{
double x, term, result;
int n, i;
long fact;
int sign;
printf("Enter x (in radians): ");
if (scanf("%lf", &x) != 1) {
printf("Invalid input.\n");
return 1;
}
printf("How many terms? ");
if (scanf("%d", &n) != 1 || n < 1) {
printf("Enter a positive number of terms.\n");
return 1;
}
result = 0.0;
sign = 1;
for (i = 0; i < n; i++) {
int power = 2 * i + 1; /* exponent: 1, 3, 5, 7, ... */
int j;
fact = 1;
for (j = 1; j <= power; j++)
fact *= j;
term = sign * pow(x, power) / (double)fact;
result += term;
sign = -sign;
}
printf("\nsin(%.4f) using %d terms = %.6f\n", x, n, result);
printf("sin(%.4f) from math.h = %.6f\n", x, sin(x));
return 0;
}
How to Compile and Run
gcc -ansi -Wall -Wextra sintaylor.c -o sintaylor -lm
./sintaylor
Sample Output
Enter x (in radians): 1.5708 How many terms? 5 sin(1.5708) using 5 terms = 1.000004 sin(1.5708) from math.h = 1.000000
Enter x (in radians): 1.0 How many terms? 10 sin(1.0000) using 10 terms = 0.841471 sin(1.0000) from math.h = 0.841471
Code Explanation
- Alternating sign with
sign = -sign— starting at 1 and flipping each iteration gives the +1, −1, +1, −1, … pattern of the Taylor series. This is cleaner than computingpow(-1, i), which would use floating-point unnecessarily for a purely integer sign. - Exponent formula
2*i + 1— when i=0,1,2,3,4, the exponents are 1,3,5,7,9. This avoids maintaining a separate “current power” variable that needs to be updated by +2 each iteration. - Inner loop for factorial — computing the factorial inside the outer loop by starting fresh each iteration is straightforward but redundant:
fact(2i+1)=fact(2i-1) * (2i) * (2i+1). For a production implementation, maintain a running factorial and multiply by two new factors each iteration — this avoids repeating multiplications and allows more terms without overflow. - Comparison with
sin()frommath.h— printing both lets you see how many terms are needed for full double-precision convergence. For small x, convergence is fast; for large x (e.g., x=100), the series converges slowly and may lose precision due to catastrophic cancellation of large terms. long fact— factorial grows quickly: 13! = 6,227,020,800, which overflows a 32-bit int. Usinglong(at least 32 bits; 64 bits on most modern platforms) extends the safe range to around 20!. Beyond ~10 terms, switch todoublefactorial accumulated in floating point to avoid integer overflow entirely.
What This Program Teaches
- Taylor series as a computational technique — every transcendental function (sin, cos, exp, ln) has a Taylor series. Computer hardware uses minimax polynomial approximations (a refinement of Taylor) to implement these functions in the FPU. Understanding the series gives you insight into how these “magic” functions actually work.
- Convergence and truncation error — the more terms you add, the closer the partial sum gets to the true value. The difference between the partial sum and the true value is the truncation error. For sin(x) with small |x|, convergence is fast; for large |x|, reduce x using the identity sin(x) = sin(x mod 2π) first.
- Factorial overflow — 21! already exceeds 64-bit unsigned integer range. Real implementations compute the series term recursively: each term is the previous term multiplied by a small ratio, avoiding direct factorial computation entirely.
Related Programs
- Quadratic Equation Roots in C
- Mean, Variance, Standard Deviation in C
- GCD and LCM in C
- Factorial Using Recursion in C
- Fibonacci Sequence Using Array in C
Recommended book:
The C Programming Language — Kernighan & Ritchie (India) |
(US)
|
C Programming: A Modern Approach — K.N. King (India) |
(US)
Practice what you learned: C Aptitude Questions — or try our C Programming Quiz App on Android.