Java中double到BigDecimal的转换

Java中double到BigDecimal的转换,java,double,bigdecimal,complex-numbers,Java,Double,Bigdecimal,Complex Numbers,我编写了一个Java程序来计算的值。在程序内部,我创建了一个库来计算必要的复杂函数,如atan、cos等。两个程序中的所有内容都是通过double和BigDecimal数据类型访问的。这会在评估Zeta函数的大值时产生重大问题 Zeta函数参考的数值逼近 当s具有较大的复杂形式时,直接以较高的值计算此近似值会产生问题,例如s=(230+30i)。我非常感激能得到这方面的信息。S2.减号(S1)的计算会产生错误,因为我在adaptiveQuad方法中写了一些错误 例如,Zeta(2+3i)通过此

我编写了一个Java程序来计算的值。在程序内部,我创建了一个库来计算必要的复杂函数,如atan、cos等。两个程序中的所有内容都是通过
double
BigDecimal
数据类型访问的。这会在评估Zeta函数的大值时产生重大问题

Zeta函数参考的数值逼近

s
具有较大的复杂形式时,直接以较高的值计算此近似值会产生问题,例如
s=(230+30i)
。我非常感激能得到这方面的信息。
S2.减号(S1)
的计算会产生错误,因为我在
adaptiveQuad
方法中写了一些错误

例如,
Zeta(2+3i)
通过此程序生成

计算形式为Zeta(s)=a+ib的黎曼Zeta函数。
在Riemann Zeta函数中输入[a]的值:2
在Riemann Zeta函数中输入[b]的值:3
Zeta(s)的值为7.9802198581133409e-1-1.137443081631288E-1*i
总时间为0.469秒。
是的

Zeta(100+0i)

计算形式为Zeta(s)=a+ib的黎曼Zeta函数。
在Riemann Zeta函数中输入[a]的值:100
在Riemann Zeta函数中输入[b]的值:0
Zeta的值为1.000000000153236E0
所用总时间为0.672秒。
这与其他方法相比也是正确的。该问题是由标记为
adaptiveQuad
的方法内部的某些内容引起的

Zeta(230+30i)

计算形式为Zeta(s)=a+ib的黎曼Zeta函数。
在Riemann Zeta函数中输入[a]的值:230
在Riemann Zeta函数中输入[b]的值:30
Zeta(s)的值是0.999999990909108519845391615339162047254997503854254327939165160684246153982012489787014797711446814567257766441212850988130425915012047816838603847693210844739256205723154167157217280824684724672467499310913504362891191509730873870909918493750428783837552525280693498787878787878787878787878787446900-38.005428584222228490409209292044031338674747488795053570481276480687488780504302949989766663616230972126423385487374863788363786029170239477711991086845577789170147132850500691609991921139705106911047250679664182062256166419533972054228386978638056565656567245197290756021581247961260937154293062734500E-15*i
总时间为1.746秒。
与之相比,虚部有点偏

计算积分的算法称为,并找到了
double
Java实现。自适应四元方法应用以下内容

//自适应正交
公共静态双自适应(双a、双b){
双h=b-a;
双c=(a+b)/2.0;
双d=(a+c)/2.0;
双e=(b+c)/2.0;
双Q1=h/6*(f(a)+4*f(c)+f(b));
双Q2=h/12*(f(a)+4*f(d)+2*f(c)+4*f(e)+f(b));
如果(算术平均值(第2季度至第1季度)0.0){
返回formatter.format(re)+“+”+formatter.format(im)
+“*我”;
}
如果(re.doubleValue()!=0.0&&im.doubleValue()<0.0){
返回formatter.format(re)+“-”+formatter.format(im.negate())
+“*我”;
}
如果(im.doubleValue()==0.0){
返回格式化程序。格式化(re);
}
如果(re.doubleValue()==0.0){
返回格式化程序。格式化(im)+“*i”;
}
返回formatter.format(re)+“+i*”+formatter.format(im);
}
}
我正在复习下面的答案

一个问题可能是由于

complenum=(z.multiply(Math.atan(t))).sin();
络合物D1=新络合物(1+t*t).pow(z.divide(TWO));
复数D2=新复数(Math.pow(Math.E,2.0*Math.PI*t)-1.0);
复数den=D1.multiply(D2,MathContext.UNLIMITED);
我没有应用
BigDecimal.pow(BigDecimal)
。尽管如此,我不认为这是导致浮点运算产生差异的直接原因

编辑:我尝试了Zeta函数的一种新的积分近似。最后,我将开发一种新方法来计算
BigDecimal.pow(BigDecimal)
(1)积分使用AdapterQuad,从区间[0,10]开始。对于a和b=0的值越来越大的z=a+ib,被积函数是一个越来越振荡的函数,仅[0,5]中的零数就与a成正比,对于z=100,被积函数增加到43

因此,从包含一个或多个零的区间开始近似是有风险的,正如发布的程序非常清楚地显示的那样。对于z=100,被积函数在0、5和10处分别为0、-2.08E-78和7.12E-115。因此,将辛普森公式的结果与1E-20进行比较,结果为真,结果绝对错误

(2) AbelPlana方法中的计算涉及两个复数,C1和C2。对于z=a+0i,它们是实数,下表显示了各种a值的值:

  a    C1          C2
 10    5.689E1     1.024E3
 20    2.759E4     1.048E6
 30    1.851E7     1.073E9
 40    1.409E10    1.099E12
 60    9.770E15    1.152E18
100    6.402E27    1.267E30
现在我们知道,随着a的增加,ζ(a+0i)的值向1减小。显然,两个大于1E15的值相减时,不可能在一个值附近产生有意义的结果

该表还表明,为了通过使用该算法获得ζ(a+0i)的良好结果,C1和C2*I(I是整数)需要以大约45位有效数字的精度进行计算。(任意精度的数学无法避免(1)中所述的陷阱。)

(3) 请注意,当使用具有任意精度的库时,像E和PI这样的值应该提供比java.lang.Math中的双精度值更好的精度

编辑 (25.5.11)在[0,10]中有与(25.5.12)一样多的零。0处的计算是t
import java.io.PrintWriter;
import org.apfloat.ApcomplexMath;
import org.apfloat.Apcomplex;
import org.apfloat.Apfloat;
import org.apfloat.samples.Pi;

public class ZetaFinder
{
    //Number of sig figs accuracy.  Note that infinite should be reserved
    private static long PRECISION = 40l; 
    // Convergence criterion for integration
    static Apfloat EPSILON = new Apfloat("1e-15",PRECISION);

    //Value of PI - enhanced using Apfloat library sample calculation of Pi in constructor,
    //Fast enough that we don't need to hard code the value in.
    //You could code hard value in for perf enhancement
    static Apfloat PI = null; //new Apfloat("3.14159"); 

    //Integration limits - I found too high a value for "infinity" causes integration
    //to terminate on first iteration.  Plot the integrand to see why...
    static Apfloat INFINITE_LIMIT = new Apfloat("40",PRECISION);
    static Apfloat ZERO_LIMIT = new Apfloat("1e-16",PRECISION); //You can use zero for the 25.5.12

    static Apfloat one = new Apfloat("1",PRECISION);
    static Apfloat two = new Apfloat("2",PRECISION);
    static Apfloat four = new Apfloat("4",PRECISION);
    static Apfloat six = new Apfloat("6",PRECISION);
    static Apfloat twelve = new Apfloat("12",PRECISION);
    static Apfloat fifteen = new Apfloat("15",PRECISION);

    static int counter = 0;

    Apcomplex s = null;

    public ZetaFinder(Apcomplex s)
    {
        this.s = s;
        Pi.setOut(new PrintWriter(System.out, true));
        Pi.setErr(new PrintWriter(System.err, true));
        PI = (new Pi.RamanujanPiCalculator(PRECISION+10, 10)).execute(); //Get Pi to a higher precision than integer consts
        System.out.println("Created a Zeta Finder based on Abel-Plana for s="+s.toString() + " using PI="+PI.toString());
    }

    public static void main(String[] args)
    {
        Apfloat re = new Apfloat("2", PRECISION);
        Apfloat im = new Apfloat("3", PRECISION);
        Apcomplex s = new Apcomplex(re,im);

        ZetaFinder finder = new ZetaFinder(s);

        System.out.println(finder.findZeta());
    }

    private Apcomplex findZeta()
    {
        Apcomplex retval = null;

        //Method currently in question (a.k.a. 25.5.12)
        //Apcomplex mult = ApcomplexMath.pow(two, this.s);
        //Apcomplex firstterm = (ApcomplexMath.pow(two, (this.s.add(one.negate())))).divide(this.s.add(one.negate()));

        //Easier integrand method (a.k.a. 25.5.11)
        Apcomplex mult = two;
        Apcomplex firstterm = (one.divide(two)).add(one.divide(this.s.add(one.negate())));

        Apfloat limita = ZERO_LIMIT;//Apfloat.ZERO;
        Apfloat limitb = INFINITE_LIMIT;
        System.out.println("Trying to integrate between " + limita.toString() + " and " + limitb.toString());
        Apcomplex integral = adaptiveQuad(limita, limitb);
        retval = firstterm.add((mult.multiply(integral)));
        return retval;
    }

    private Apcomplex adaptiveQuad(Apfloat a, Apfloat b) {
        //if (counter % 100 == 0)
        {
            System.out.println("In here for the " + counter + "th time");
        }
        counter++;
        Apfloat h = b.add(a.negate());
        Apfloat c = (a.add(b)).divide(two);
        Apfloat d = (a.add(c)).divide(two);
        Apfloat e = (b.add(c)).divide(two);

        Apcomplex Q1 = (h.divide(six)).multiply(f(a).add(four.multiply(f(c))).add(f(b)));
        Apcomplex Q2 = (h.divide(twelve)).multiply(f(a).add(four.multiply(f(d))).add(two.multiply(f(c))).add(four.multiply(f(e))).add(f(b)));
        if (ApcomplexMath.abs(Q2.add(Q1.negate())).compareTo(EPSILON) < 0)
        {
            System.out.println("Returning");
            return Q2.add((Q2.add(Q1.negate())).divide(fifteen));
        }
        else
        {
            System.out.println("Recursing with intervals "+a+" to " + c + " and " + c + " to " +d);
            return adaptiveQuad(a, c).add(adaptiveQuad(c, b));
        }
    }

    private Apcomplex f(Apfloat x)
    {
        return integrand2(x);
    }

    /*
     * Simple test integrand (z^2)
     * 
     * Can test implementation by asserting that the adaptiveQuad
     * with this function evaluates to z^3 / 3
     */
    private Apcomplex integrandTest(Apfloat t)
    {
        return ApcomplexMath.pow(t, two);
    }

    /*
     * Abel-Plana formulation integrand
     */
    private Apcomplex integrand1(Apfloat t)
    {
        Apcomplex numerator = ApcomplexMath.sin(this.s.multiply(ApcomplexMath.atan(t)));
        Apcomplex bottomlinefirstbr = one.add(ApcomplexMath.pow(t, two));
        Apcomplex D1 = ApcomplexMath.pow(bottomlinefirstbr, this.s.divide(two));
        Apcomplex D2 = (ApcomplexMath.exp(PI.multiply(t))).add(one);    
        Apcomplex denominator = D1.multiply(D2);
        Apcomplex retval = numerator.divide(denominator);       
        //System.out.println("Integrand evaluated at "+t+ " is "+retval);
        return retval;
    }

    /*
     * Abel-Plana formulation integrand 25.5.11 
     */
    private Apcomplex integrand2(Apfloat t)
    {
        Apcomplex numerator = ApcomplexMath.sin(this.s.multiply(ApcomplexMath.atan(t)));
        Apcomplex bottomlinefirstbr = one.add(ApcomplexMath.pow(t, two));
        Apcomplex D1 = ApcomplexMath.pow(bottomlinefirstbr, this.s.divide(two));
        Apcomplex D2 = ApcomplexMath.exp(two.multiply(PI.multiply(t))).add(one.negate());    
        Apcomplex denominator = D1.multiply(D2);
        Apcomplex retval = numerator.divide(denominator);       
        //System.out.println("Integrand evaluated at "+t+ " is "+retval);
        return retval;
    }
}
import java.io.PrintWriter;

import org.apfloat.ApcomplexMath;
import org.apfloat.Apcomplex;
import org.apfloat.Apfloat;
import org.apfloat.ApfloatMath;
import org.apfloat.samples.Pi;

public class ZetaSeries {

    //Number of sig figs accuracy.  Note that infinite should be reserved
    private static long PRECISION = 100l; 
    // Convergence criterion for integration
    static Apfloat EPSILON = new Apfloat("1e-30",PRECISION);

    static Apfloat one = new Apfloat("1",PRECISION);
    static Apfloat two = new Apfloat("2",PRECISION);
    static Apfloat minus_one = one.negate();
    static Apfloat three = new Apfloat("3",PRECISION);

    private Apcomplex s = null;
    private Apcomplex s_plus_two = null;


    public ZetaSeries(Apcomplex s) {
        this.s = s;
        this.s_plus_two = two.add(s);
    }

    public static void main(String[] args) {

        Apfloat re = new Apfloat("230", PRECISION);
        Apfloat im = new Apfloat("30", PRECISION);
        Apcomplex s = new Apcomplex(re,im);
        ZetaSeries z = new ZetaSeries(s);
        System.out.println(z.findZeta());
    }

    private Apcomplex findZeta() {

        Apcomplex series_sum = Apcomplex.ZERO;
        Apcomplex multiplier = (one.divide(this.s.add(minus_one)));
        int stop_condition = 1;
        long n = 1;
        while (stop_condition > 0)
        {
            Apcomplex term_to_add = sum_term(n);
            stop_condition = ApcomplexMath.abs(term_to_add).compareTo(EPSILON);
            series_sum = series_sum.add(term_to_add);
            //if(n%50 == 0)
            {
                System.out.println("At iteration " + n + " : " + multiplier.multiply(series_sum));
            }
            n+=1;
        }
        return multiplier.multiply(series_sum);
    }

    private Apcomplex sum_term(long n_long) {
        Apfloat n = new Apfloat(n_long, PRECISION);
        Apfloat n_plus_one = n.add(one);
        Apfloat two_n = two.multiply(n);

        Apfloat t1 = (n.multiply(n_plus_one)).divide(two);
        Apcomplex t2 = (two_n.add(three).add(this.s)).divide(ApcomplexMath.pow(n_plus_one,s_plus_two));
        Apcomplex t3 = (two_n.add(minus_one).add(this.s.negate())).divide(ApcomplexMath.pow(n,this.s_plus_two));
        return t1.multiply(t2.add(t3.negate()));
    }

}