Zeta Riemann function in Java - infinite recursion with functional form

Note: Updated 06.17.2012. Of course it is possible. See Solution below.

Even if someone copies and pastes this code, you still have a lot of room for cleaning. Also note that you will have problems inside the critical band from Re (s) = 0 to Re (s) = 1 :). But this is a good start.

import java.util.Scanner; public class NewTest{ public static void main(String[] args) { RiemannZetaMain func = new RiemannZetaMain(); double s = 0; double start, stop, totalTime; Scanner scan = new Scanner(System.in); System.out.print("Enter the value of s inside the Riemann Zeta Function: "); try { s = scan.nextDouble(); } catch (Exception e) { System.out.println("You must enter a positive integer greater than 1."); } start = System.currentTimeMillis(); if (s <= 0) System.out.println("Value for the Zeta Function = " + riemannFuncForm(s)); else if (s == 1) System.out.println("The zeta funxtion is undefined for Re(s) = 1."); else if(s >= 2) System.out.println("Value for the Zeta Function = " + getStandardSum(s)); else System.out.println("Value for the Zeta Function = " + getNewSum(s)); stop = System.currentTimeMillis(); totalTime = (double) (stop-start) / 1000.0; System.out.println("Total time taken is " + totalTime + " seconds."); } // Standard form the the Zeta function. public static double standardZeta(double s) { int n = 1; double currentSum = 0; double relativeError = 1; double error = 0.000001; double remainder; while (relativeError > error) { currentSum = Math.pow(n, -s) + currentSum; remainder = 1 / ((s-1)* Math.pow(n, (s-1))); relativeError = remainder / currentSum; n++; } System.out.println("The number of terms summed was " + n + "."); return currentSum; } public static double getStandardSum(double s){ return standardZeta(s); } //New Form // zeta(s) = 2^(-1+2 s)/((-2+2^s) Gamma(1+s)) integral_0^infinity t^s sech^2(t) dt for Re(s)>-1 public static double Integrate(double start, double end) { double currentIntegralValue = 0; double dx = 0.0001d; // The size of delta x in the approximation double x = start; // A = starting point of integration, B = ending point of integration. // Ending conditions for the while loop // Condition #1: The value of b - x(i) is less than delta(x). // This would throw an out of bounds exception. // Condition #2: The value of b - x(i) is greater than 0 (Since you start at A and split the integral // up into "infinitesimally small" chunks up until you reach delta(x)*n. while (Math.abs(end - x) >= dx && (end - x) > 0) { currentIntegralValue += function(x) * dx; // Use the (Riemann) rectangle sums at xi to compute width * height x += dx; // Add these sums together } return currentIntegralValue; } private static double function(double s) { double sech = 1 / Math.cosh(s); // Hyperbolic cosecant double squared = Math.pow(sech, 2); return ((Math.pow(s, 0.5)) * squared); } public static double getNewSum(double s){ double constant = Math.pow(2, (2*s)-1) / (((Math.pow(2, s)) -2)*(gamma(1+s))); return constant*Integrate(0, 1000); } // Gamma Function - Lanczos approximation public static double gamma(double s){ double[] p = {0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7}; int g = 7; if(s < 0.5) return Math.PI / (Math.sin(Math.PI * s)*gamma(1-s)); s -= 1; double a = p[0]; double t = s+g+0.5; for(int i = 1; i < p.length; i++){ a += p[i]/(s+i); } return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5)*Math.exp(-t)*a; } //Binomial Co-efficient - NOT CURRENTLY USING /* public static double binomial(int n, int k) { if (k>nk) k=nk; long b=1; for (int i=1, m=n; i<=k; i++, m--) b=b*m/i; return b; } */ // Riemann Functional Equation // Tried this initially and utterly failed. public static double riemannFuncForm(double s) { double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s); double nextTerm = Math.pow(2, (1-s))*Math.pow(Math.PI, (1-s)-1)*(Math.sin((Math.PI*(1-s))/2))*gamma(1-(1-s)); double error = Math.abs(term - nextTerm); if(s == 1.0) return 0; else return Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)*standardZeta(1-s); } 

}

+5
source share
3 answers

I think I need to use a different form of zeta function. When I run the whole program ---

 import java.util.Scanner; public class Test4{ public static void main(String[] args) { RiemannZetaMain func = new RiemannZetaMain(); double s = 0; double start, stop, totalTime; Scanner scan = new Scanner(System.in); System.out.print("Enter the value of s inside the Riemann Zeta Function: "); try { s = scan.nextDouble(); } catch (Exception e) { System.out.println("You must enter a positive integer greater than 1."); } start = System.currentTimeMillis(); if(s >= 2) System.out.println("Value for the Zeta Function = " + getStandardSum(s)); else System.out.println("Value for the Zeta Function = " + getRiemannSum(s)); stop = System.currentTimeMillis(); totalTime = (double) (stop-start) / 1000.0; System.out.println("Total time taken is " + totalTime + " seconds."); } // Standard form the the Zeta function. public static double standardZeta(double s) { int n = 1; double currentSum = 0; double relativeError = 1; double error = 0.000001; double remainder; while (relativeError > error) { currentSum = Math.pow(n, -s) + currentSum; remainder = 1 / ((s-1)* Math.pow(n, (s-1))); relativeError = remainder / currentSum; n++; } System.out.println("The number of terms summed was " + n + "."); return currentSum; } public static double getStandardSum(double s){ return standardZeta(s); } // Riemann Functional Equation public static double riemannFuncForm(double s, double threshold, double currSteps, int maxSteps) { double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s); //double nextTerm = Math.pow(2, (1-s))*Math.pow(Math.PI, (1-s)-1)*(Math.sin((Math.PI*(1-s))/2))*gamma(1-(1-s)); //double error = Math.abs(term - nextTerm); if(s == 1.0) return 0; else if (s == 0.0) return -0.5; else if (term < threshold) {//The recursion will stop once the term is less than the threshold System.out.println("The number of steps is " + currSteps); return term; } else if (currSteps == maxSteps) {//The recursion will stop if you meet the max steps System.out.println("The series did not converge."); return term; } else //Otherwise just keep recursing return term*riemannFuncForm(1-s, threshold, ++currSteps, maxSteps); } public static double getRiemannSum(double s) { double threshold = 0.00001; double currSteps = 1; int maxSteps = 1000; return riemannFuncForm(s, threshold, currSteps, maxSteps); } // Gamma Function - Lanczos approximation public static double gamma(double s){ double[] p = {0.99999999999980993, 676.5203681218851, -1259.1392167224028, 771.32342877765313, -176.61502916214059, 12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7}; int g = 7; if(s < 0.5) return Math.PI / (Math.sin(Math.PI * s)*gamma(1-s)); s -= 1; double a = p[0]; double t = s+g+0.5; for(int i = 1; i < p.length; i++){ a += p[i]/(s+i); } return Math.sqrt(2*Math.PI)*Math.pow(t, s+0.5)*Math.exp(-t)*a; } //Binomial Co-efficient public static double binomial(int n, int k) { if (k>nk) k=nk; long b=1; for (int i=1, m=n; i<=k; i++, m--) b=b*m/i; return b; } 

}

I notice that turning on zeta (-1) is returning -

 Enter the value of s inside the Riemann Zeta Function: -1 The number of steps is 1.0 Value for the Zeta Function = -0.0506605918211689 Total time taken is 0.0 seconds. 

I knew this value was -1/12. I checked some other values ​​with wolfram alpha and noticed that -

 double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s); 

Returns the correct value. I just multiply this value every time by zeta (1-s). In the case of Zeta (1/2), this will always multiply the result by 0.99999999.

 Enter the value of s inside the Riemann Zeta Function: 0.5 The series did not converge. Value for the Zeta Function = 0.999999999999889 Total time taken is 0.006 seconds. 

I will see if I can replace the part with -

  else if (term < threshold) {//The recursion will stop once the term is less than the threshold System.out.println("The number of steps is " + currSteps); return term; } 

This difference is a mistake between two members in the summation. Maybe I don't think about it right, now 1:16. Let me see if I can think better tomorrow.

-1
source

Well, we found out that for this particular function, since this form of this is not actually an infinite series, we cannot approximate the use of recursion. However, through this method it would be possible to solve the infinite sum of Riemann zeta series ( 1\(n^s) where n = 1 to infinity ).

In addition, this method could be used to find any amount, product or limit of an infinite series.

If you execute the code that you currently have, you will get infinite recursion like 1-(1-s) = s (e.g. 1-s = t , 1-t = s , so that you simply switch between the two s values infinitely).

Below I will talk about the sum of the series. It seems you are calculating a series product. The concepts below should also work.

In addition, Zeta Function is an endless series . This means that it has only a limit and will never reach the true amount (in a finite time), and therefore you will not be able to get an exact answer through recursion.

However, if you enter a “threshold” coefficient, you can get an approximation that is as good as you like. The amount will increase / decrease as each term is added. Once the amount has stabilized, you can exit the recursion and return your approximate amount. “Stable” is determined using your threshold coefficient. When the amount changes by an amount less than this threshold coefficient (which you determined), your amount has stabilized.

A lower threshold leads to a better approximation, but also to a longer calculation time.

(Note: this method only works if your series converges, if you have a chance of not converging, you can also build the maxSteps variable to stop execution if the series does not converge to your satisfaction after the maxSteps recursion steps.)

Here's an example implementation, note that you will need to play with threshold and maxSteps to determine the appropriate values:

 /* Riemann Functional Equation * threshold - if two terms differ by less than this absolute amount, return * currSteps/maxSteps - if currSteps becomes maxSteps, give up on convergence and return * currVal - the current product, used to determine threshold case (start at 1) */ public static double riemannFuncForm(double s, double threshold, int currSteps, int maxSteps, double currVal) { double nextVal = currVal*(Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)); //currVal*term if( s == 1.0) return 0; else if ( s == 0.0) return -0.5; else if (Math.abs(currVal-nextVal) < threshold) //When a term will change the current answer by less than threshold return nextVal; //Could also do currVal here (shouldn't matter much as they differ by < threshold) else if (currSteps == maxSteps)//When you've taken the max allowed steps return nextVal; //You might want to print something here so you know you didn't converge else //Otherwise just keep recursing return riemannFuncForm(1-s, threshold, ++currSteps, maxSteps, nextVal); } } 
+3
source

It's impossible.

The functional form of the Riemann zeta function is

 zeta(s) = 2^s pi^(-1+s) Gamma(1-s) sin((pi s)/2) zeta(1-s) 

This differs from the standard equation in which the infinite sum is measured from 1 / k ^ s for all k = 1 to k = infinity. It can be written as something similar to -

 // Standard form the the Zeta function. public static double standardZeta(double s) { int n = 1; double currentSum = 0; double relativeError = 1; double error = 0.000001; double remainder; while (relativeError > error) { currentSum = Math.pow(n, -s) + currentSum; remainder = 1 / ((s-1)* Math.pow(n, (s-1))); relativeError = remainder / currentSum; n++; } System.out.println("The number of terms summed was " + n + "."); return currentSum; } 

The same logic does not apply to a functional equation (this is not a direct sum, it is a mathematical relation). This will require a fairly smart way to develop a program to calculate negative values ​​of Zeta (s)!

A literal interpretation of this Java code --- ---

 // Riemann Functional Equation public static double riemannFuncForm(double s) { double currentVal = (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)); if( s == 1.0) return 0; else if ( s == 0.0) return -0.5; else System.out.println("Value of next value is " + nextVal(1-s)); return currentVal;//*nextVal(1-s); } public static double nextVal(double s) { return (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)); } public static double getRiemannSum(double s) { return riemannFuncForm(s); } 

Testing with three or four values ​​shows that this does not work. If you write something similar to -

 // Riemann Functional Equation public static double riemannFuncForm(double s) { double currentVal = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s); //currVal*term if( s == 1.0) return 0; else if ( s == 0.0) return -0.5; else //Otherwise just keep recursing return currentVal * nextVal(1-s); } public static double nextVal(double s) { return (Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s)); } 

I misunderstood how to do this using math. I will have to use a different zeta function approximation for values ​​less than 2.

0
source

All Articles