Java中的Riemann-Zeta函数&函数形式的无限递归
注:于2015年6月17日更新。当然这是可能的。请参阅下面的解决方案 即使有人复制并粘贴了这段代码,您仍然有很多清理工作要做。还要注意的是,从Re(s)=0到Re(s)=1:)的关键条带内会出现问题。但这是一个良好的开端Java中的Riemann-Zeta函数&函数形式的无限递归,java,recursion,number-theory,Java,Recursion,Number Theory,注:于2015年6月17日更新。当然这是可能的。请参阅下面的解决方案 即使有人复制并粘贴了这段代码,您仍然有很多清理工作要做。还要注意的是,从Re(s)=0到Re(s)=1:)的关键条带内会出现问题。但这是一个良好的开端 import java.util.Scanner; public class NewTest{ public static void main(String[] args) { RiemannZetaMain func = new RiemannZetaMain()
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>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
} */
// Riemann's 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);
}
import java.util.Scanner;
公共类新测试{
公共静态void main(字符串[]args){
RiemannZetaMain func=新的RiemannZetaMain();
双s=0;
双重启动、停止、总时间;
扫描仪扫描=新扫描仪(System.in);
System.out.print(“在Riemann Zeta函数中输入s的值:”);
试一试{
s=scan.nextDouble();
}
捕获(例外e){
System.out.println(“必须输入大于1的正整数”);
}
start=System.currentTimeMillis();
如果(s=2)
System.out.println(“Zeta函数的值=“+getStandardSum”);
其他的
System.out.println(“Zeta函数的值=“+getNewSum”);
停止=System.currentTimeMillis();
总时间=(双倍)(停止-启动)/1000.0;
System.out.println(“所用的总时间为”+totalTime+“秒”);
}
//标准形式的Zeta函数。
公共静态双标准Zeta(双s){
int n=1;
双电流和=0;
双相对误差=1;
双误差=0.000001;
双倍余数;
while(相对错误>错误){
currentSum=数学功率(n,-s)+currentSum;
余数=1/((s-1)*数学功率(n,(s-1));
相对误差=余数/当前和;
n++;
}
System.out.println(“合计的术语数为“+n+”);
返回电流和;
}
公共静态双getStandardSum(双s){
返回标准泽塔;
}
//新形式
//zeta(s)=2^(-1+2 s)/(-2+2^s)伽马(1+s))积分_0^无穷大t^s秒^2(t)dt对于Re(s)>-1
公共静态双积分(双起点、双终点){
双电流积分值=0;
double dx=0.0001d;//近似值中的delta x的大小
double x=start;//A=积分起点,B=积分终点。
//while循环的结束条件
//条件#1:b-x(i)的值小于δ(x)。
//这将抛出一个越界异常。
//条件#2:b-x(i)的值大于0(因为从A开始并拆分积分)
//直到你到达δ(x)*n。
而(Math.abs(end-x)>=dx&&(end-x)>0){
CurrnTrimalValue+=函数(x)*dx;//使用席(黎曼)矩形求和计算宽度*高度
x+=dx;//将这些总和相加
}
返回当前值;
}
专用静态双功能(双s){
double sech=1/Math.cosh(s);//双曲余割
双平方=数学功率(秒,2);
返回值((数学功率,0.5))*平方;
}
公共静态双getNewSum(双s){
双常数=数学功率(2,(2*s)-1/((数学功率(2,s))-2)*(伽马(1+s));
返回常数*积分(0,1000);
}
//Gamma函数-Lanczos近似
公共静态双伽马(双s){
双[]p={0.99999999980993676.520368218851,-1259.139216722428,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012、9.984369578019516E-6、1.5056327351493116e-7};
int g=7;
如果(s<0.5)返回Math.PI/(Math.sin(Math.PI*s)*gamma(1-s));
s-=1;
双a=p[0];
双t=s+g+0.5;
对于(int i=1;in-k)
k=n-k;
长b=1;
对于(int i=1,m=n;i好的,我们已经发现,对于这个特殊的函数,因为它的这种形式实际上不是一个无穷级数,我们不能用递归来近似。然而,Riemann-Zeta级数的无穷和(1\(n^s),其中n=1到无穷大
)可以通过这个方法来求解
此外,此方法可用于查找任何无穷级数的和、积或极限。
如果您执行当前拥有的代码,您将得到无限递归,如1-(1-s)=s
(例如1-s=t
,1-t=s
,因此您只需在s
的两个值之间无限地来回切换)
下面我讲的是级数的和。看起来你是在计算级数的乘积。下面的概念应该适用于这两种情况
除此之外,Riemann Zeta函数是一个。这意味着它只有一个极限,永远不会达到真和(在有限时间内),因此你无法通过递归得到确切的答案
但是,如果引入“阈值”因子,则可以得到一个近似值。随着每个项的添加,总和将增加/减少。一旦总和稳定,您可以退出递归并返回近似总和。“稳定”使用您的阈值因子定义。一旦总和的变化量小于此阈值因子(您已定义),则总和已稳定
阈值越小,逼近效果越好,但计算时间也越长
(注意:此方法仅在序列收敛时有效,如果它有可能不收敛,您可能还希望在maxSteps
递归步骤后,如果序列没有收敛到令您满意的程度,则构建maxSteps
变量以停止执行。)
这里是一个示例实现,请注意,您必须使用threshold
和
/* Riemann's 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);
}
}
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's 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>n-k)
k=n-k;
long b=1;
for (int i=1, m=n; i<=k; i++, m--)
b=b*m/i;
return b;
}
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.
double term = Math.pow(2, s)*Math.pow(Math.PI, s-1)*(Math.sin((Math.PI*s)/2))*gamma(1-s);
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.
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;
}
zeta(s) = 2^s pi^(-1+s) Gamma(1-s) sin((pi s)/2) zeta(1-s)
// 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;
}
// Riemann's 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);
}
// Riemann's 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));
}