Riemann zeta loops.

Hallo there,

I have to make a program which will solve Riemann zeta function(2) [1/pow(n,2)] = 1,645... It has to calculate it in 3 ways.
1. For loop witch was easy and I did it by myself
1
2
3
4
5
6
7
8
  
	for (i = 1; i <= 1000; i++)
	{
		n = 1 / pow(i, 2);
		sum += n;
	}
	cout << sum << endl;


2. While loop. And here's a problem. It has to calculate same task, but it has to stop when numver will have six decimal places.
3. Do... while loop. Here's second problem. It has to calculate same task, but it has to calculate it as accurately as it is possible.

I will appreciate any help.
Thank you very much.
Last edited on
(If you want an accurate answer it is pi * pi / 6)

Your Task 2 is about truncation errors (approximating an infinite series by a finite number of terms.
Your Task 3 is about rounding errors (the accuracy with which a computer can represent a number).

Pseudocode for your task 2 might look like:
while ( error bound > tolerance )
{
     your existing addition to sum;
     increment a counter;
}

Your tolerance for an accuracy of 6 decimal places will be 0.5e-6.
You will need to find an error bound for the terms you have omitted. One such can be derived by considering the area under the curve y=1/x^2 - the terms in your series are rectangular bars that lie strictly underneath that curve, so the area under the curve will exceed them and, by integration, provide you with an error bound for the omitted terms.
Note that the size of one term is not an adequate criterion for terminating the loop in this instance.


I am more hazy about your task 3. The accuracy with which individual numeric types can be represented should be available in
<limits>
http://www.cplusplus.com/reference/limits/numeric_limits/
and you can stop looping when your terms are less than the smallest identifiable non-zero number (or your counter exceeds the largest representable integer).

Thank very much you for help. I did it few minutes ago. It's not exactly how it has to be, but it works at least. Every loop calculate it more precisely, but every loop has the same number of decimal places. I'll add code in another post. Maybe it will help someone in the future
#include <conio.h>
#include <iostream>
#include <cmath>

double sum, sum2, sum3, old;
int i;
using namespace std;

int main()
{
	cout.precision(14);

	sum = 0;
	
	for (i = 1; i < 1000; i++)
	{
		sum += 1 / (pow(double(i), 2));
	}
	cout << "For " << sum << endl;

	sum2 = 0;
	double b = 1;
	double c = 0;
	double x = 0.000001;

	do
	{
		c = (1 / pow(double(b), 2));
		sum2 += c;
		b++;
	}
	while (c > x);
	cout << "Do...while: " << sum2 << endl;

	sum3 = 0;
	b = 1;
	old = 1;

	while (sum3 != old)
	{
		old = sum3;
		sum3 += (1 / pow(double(b), 2));
		b++;
	}
	cout << "While: " << sum3 << endl;

	cout << "Nacisnij klawisz, aby zakonczyc program..." << endl;

	_getch();
	return 0;

}
CePP,
When I ran your code it produced the following output:
For 1.6439335666816
Do...while: 1.6439345666816
While: 1.6449340578302
Nacisnij klawisz, aby zakonczyc program...


The correct answer to 6 decimal places is 1.644934. You can check this against the exact answer pi * pi / 6.

Your second answer - the Do ... while loop - does not give this answer to 6 d.p. accuracy; (it is actually out by about 0.001, an error in the 3rd decimal place). Your convergence criterion ensures only that one term is less than 0.000001 - it doesn't mean the answer is correct to 6 d.p. Your final answer seems sensible, however.

You may be interested in one famous series where this convergence criterion would fail spectacularly: the harmonic series https://en.wikipedia.org/wiki/Harmonic_series_(mathematics) ; it is nominally zeta(1).
1/1 + 1/2 + 1/3 + 1/4 + 1/5 + ....
Even though individual terms tend to zero, the series does not actually converge. If you took a (very large) number of terms you could make the sum as big as you like. Another very famous hypothesis concerns the zeros of the zeta function for complex arguments. It is called the Riemann hypothesis (https://en.wikipedia.org/wiki/Riemann_hypothesis ). If you were able to prove this you would bring yourself everlasting fame!


If you are interested in a general zeta function try the following. (Enter 2 when prompted. You can use the little "gear wheel" at the top-right of the code sample to run it.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;

int main()
{
   double zeta;
   double tolerance = 0.5e-6;            // max error for 6 d.p. accuracy
   double result = 0.0;
   long n = 1;
 
   cout << "Input zeta ( > 1 ): ";   cin >> zeta;
 
   while ( ( zeta - 1 ) / pow( n, zeta - 1 ) > tolerance ) // based on an integral bound for error
   {
      result += 1.0 / pow( n, zeta );
      n++;
   }
   cout << "\nzeta(" << zeta << ") = " << setprecision(7) << result;
}
Last edited on
Topic archived. No new replies allowed.