Each exercise this quarter is rated on a integer scale of 1 – 5, inclusive, with 1 being the "least time-consuming" and 5 being the "most time-consuming".
This difficulty scale is meant as a rough guide for you in predicting the amount of time to set aside for each exercise as you balance the work required for 333 with your other obligations. However, it is necessarily imperfect as everyone's set of circumstances and experiences with the exercises differ. If your experience with an exercise does not align with its rating, that is not a reflection of you or your abilities.
Write a C program that approximates π using the Nilakantha series.
Your program takes a single non-negative integer n as a
command-line argument, specifying how many terms of the series to
include in the estimate. The count is inclusive of term. For example, n = 3 sums terms 0, 1, 2, and 3.
Your program should print the resulting estimate of π to 20 decimal places.
The Nilakantha series is an alternating series
that can be used to calculate the value of π. It was published in
the 15th century by a mathematician named
Nilakantha Samayaji.
It starts with a leading term of 3 (term 0) and
then adds successively smaller correction terms (terms 1,
2, 3, …):
\[ \pi = 3 + \frac{4}{2 \cdot 3 \cdot 4} - \frac{4}{4 \cdot 5 \cdot 6} + \frac{4}{6 \cdot 7 \cdot 8} - \cdots \]
Each correction term has a numerator of 4 and a denominator
that multiplies three consecutive integers starting at an even number
(2·3·4, then 4·5·6,
then 6·7·8, …), and the signs alternate.
So term n (for n ≥ 1) is
\((-1)^{n+1} \cdot \tfrac{4}{2n \cdot (2n+1) \cdot (2n+2)}\),
which lets us write the whole series compactly as:
\[ \pi = 3 + \sum_{n=1}^{\infty} (-1)^{n+1} \cdot \frac{4}{2n \cdot (2n+1) \cdot (2n+2)} \]
The Nilakantha series isn't the most famous series for estimating π. That honor usually goes to the Leibniz series, named after Gottfried Leibniz, who discovered the series in the 1670s. However, as the mathematics community began to globalize, people realized that the Leibniz series had also been discovered nearly three centuries earlier by an Indian mathematician Madhava of Sangamagrama, founder of the Kerala school of mathematics. It is sometimes referred to as the Madhava-Leibniz series.
Nilakantha belonged to that same Kerala school, and his contribution was improving on the convergence speed.
The Leibniz series (sometimes called the Madhava-Leibniz series) is considered elegant, but extremely slow. To approximate π
to ten decimal places, it takes nearly 5 billion terms. Nilakantha's
series takes some clever shortcuts and reaches the same ten decimals in roughly
1,700 terms.
While testing, you should compile your program into an executable called ex1.
$ gcc -Wall -g -std=c17 -o ex1 ex1.c $ ls ex1 ex1.c
Here ex1.c is your program and ex1 is your executable.
Here are some examples that display how your program should behave. Your output should match these exactly:
$ ./ex1 1 Our estimate of Pi is 3.16666666666666651864 $ ./ex1 10 Our estimate of Pi is 3.14140671849650177094 $ ./ex1 100 Our estimate of Pi is 3.14159241097198238535
In addition, your program should handle unexpected inputs gracefully (i.e., without crashing). For each malformed input, you may choose how you want to respond and document the decision with a short comment in your code (one or two short sentences is fine). Please consider the following cases:
$ ./ex1 $ ./ex1 hello $ ./ex1 -20 $ ./ex1 0.05432 $ ./ex1 10000000 3234
One case you can safely ignore is an integer that is too large to fit
into an int (e.g., 2333 will not fit
in 32 bits).
To convert the command-line argument from a digit-string to an
int and print the result, you'll need a handful of
standard C library functions. See
www.cplusplus.com/reference
(also linked from the C/C++ menu in the nav bar above) for
documentation; ignore the C++ pages for now.
stdio.h for basic input and output,string.h for handling C-strings (i.e., null-terminated arrays of characters), andstdlib.h for some useful functions.sscanf, atoi, strtol, and
others; think about the tradeoffs and differences between them.math.h library as it requires additional
compilation options.To avoid floating-point arithmetic errors, please make sure your code adheres to the following rules:
double type for intermediate and final results.Since this is the first exercise, we want you to get comfortable with the C best practices mentioned in the lecture.
Here are some common style issues to keep in mind:
As mentioned earlier in the spec, your program should handle user inputs in a robust way. If users enter unexpected or malformed input, your program should not crash. Instead, it should have prechecks that detect these inputs and display helpful information to the user.
There are multiple ways to handle these prechecks. If you make a design decision (i.e. choose one way over another way to handle something), then leave a comment above that code explaining why.
cpplint.py (included in your repo). When you have fixed all linter errors, you should see the following output:
$ ./cpplint.py --clint ex1.c Done processing ex1.c
valgrind:
$ valgrind ./ex1 <input> ... ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
To submit your assignment, you must:
ex1.c submissionFor full credit, your code must:
attu, or CSE
home VM). We will compile your code with the command:
$ gcc -Wall -g -std=c17 -o ex1 ex1.c
gcc and valgrind).
.c file with your name(s) and CSE or UW email
address(es).
cpplint.py --clint should run clean.