在Java中,对于涉及复数的指数函数,是否有一个好的算法来计算更精确的值?

在Java中,对于涉及复数的指数函数,是否有一个好的算法来计算更精确的值?,java,floating-point,precision,complex-numbers,exponentiation,Java,Floating Point,Precision,Complex Numbers,Exponentiation,我是Java新手,正在编写一个表示复数的类 //imports public final class Complex extends Object implements Serializable{ private final double real; private final double imaginary; public Complex(final double real, final double imagina

我是Java新手,正在编写一个表示复数的类

    //imports

    public final class Complex extends Object implements Serializable{    
        private final double real;
        private final double imaginary;

        public Complex(final double real, final double imaginary){
            this.real=real;
            this.imaginary=imaginary;
        }

        //other constructors

        //other methods

        public Complex multiply(final Complex multiplicand){
            return new Complex(this.real*multiplicand.real-this.imaginary*multiplicand.imaginary,this.real*multiplicand.imaginary+multiplicand.real*this.imaginary);        
        }

        public Complex exponentiate(final Complex exponent){
            return this.logarithm().multiply(exponent).exponentiate();
        }   

        public Complex exponentiate(){
            return new Complex(Math.exp(this.real)*Math.cos(this.imaginary),Math.exp(this.real)*Math.sin(this.imaginary));
        }

        public Complex logarithm(){
            double realPart=Math.log(Math.sqrt(Math.pow(this.real,2)+Math.pow(this.imaginary,2)));
            double imaginaryPart=Math.atan2(this.imaginary,this.real);       
            return new Complex(realPart,imaginaryPart);   
        }

        public static final Complex I=new Complex(0.,1.);     
        public static final Complex E=new Complex(Math.E,0.);
        public static final Complex PI=new Complex(Math.PI,0.);
    }
这就是我如何尝试使用Java实现复杂指数运算的原理值。然而,类中的对象使用double来表示它们的实部和虚部,这导致了严重的不精确性。 例如,如果我尝试System.out.printlnComplex.E.exponentiateComplex.PI.multiplyComplex.I;,与Euler的恒等式e^pi*i等价,结果将是-1.0+1.2246467991473532E-16i,而不仅仅是-1.0,这是由于浮点变量的不精确性


我想知道是否有任何方法可以计算出指数函数更精确的值,或者通过改进我的算法,或者采用另一种方法。感谢您阅读我的问题。

使用数学库,您可以获得的准确性是有限的。从文档中:

实现规范的质量涉及两个属性:返回结果的准确性和方法的单调性。浮点数学方法的精度是以ULP(最后一位的单位)来衡量的。对于给定的浮点格式,特定实数值的ulp是包含该数值的两个浮点值之间的距离。当作为一个整体而不是在一个特定的参数中讨论方法的准确性时,所引用的ULP数量是针对任何参数的最坏情况错误。如果一个方法的错误总是小于0.5 ulps,那么该方法总是返回最接近精确结果的浮点数;这种方法是正确的四舍五入。一个正确的四舍五入方法通常是浮点近似的最佳方法;然而,要使许多浮点方法正确地四舍五入是不切实际的。相反,对于Math类,某些方法允许1或2个ULP的更大错误范围。非正式地说,在1 ulp错误范围内,当精确结果是可表示的数字时,应将精确结果作为计算结果返回;否则,可能会返回包含精确结果的两个浮点值中的任何一个。对于大小较大的精确结果,括号的一个端点可能是无限的。除了个别参数的准确性外,在不同参数下保持方法之间的正确关系也很重要。因此,大多数ulp误差大于0.5的方法要求是半单调的:当数学函数不递减时,浮点近似也是如此,同样,当数学函数不递增时,浮点近似也是如此。并非所有具有1 ulp精度的近似值都会自动满足单调性要求

您可以在中查看每种计算方法的ulp限制


可以考虑使用双小数,但是除了一些公共可用的库之外,没有复杂的数学运算的等效支持。大小数确实允许在计算机内存范围内无限位数或精度,但无法在所有情况下提供无限精度和精确结果。如果以无限精度计算1/3,BigDecimal类将抛出一个错误。有关更多信息,请参见。

尝试Apache Commons Math 3.6.1 API

该值非常接近输入值的正确幂运算,只是该值不完全是i pi。这不是一个可以解决的问题,除非使用不同的表示形式符号、任意精度等,或者使用脆弱的破解方法,如对某些输入进行特殊封装,或者丢弃所有较小的输出组件,否则会导致更大的错误。要获得更高的精度,请使用java.math.BigDecimal,但是你仍然无法在有限的计算机内存中拟合出e或pi的精确值。在大多数实际应用中,1e-16非常接近于零。我不得不重写这篇文章,因为我首先使用了最真实的目的。你寻求更准确结果的目的是什么?一般来说,不可能得到精确的结果,因为大多数求幂结果不能用浮点格式表示。因此,您所能做的最好的事情就是进一步减少错误。为什么你需要多一点关于当前结果的不足之处,为什么只需要多一点就可以解决?如果您只是在寻找特殊情况下的“干净”结果,例如结果完全真实的情况,那么这是可能的。值得吗?您可能想看看Scala类的一些库。