我是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.println(Complex.E.exponentiate(Complex.PI.multiply(Complex.I)));
(相当于Euler身份e ^(pi * i)),结果将为 -1.0 + 1.2246467991473532E-16i ,而不是简单地< strong> -1.0 ,这是由于浮点变量的不精确所致。
我想知道是否可以通过改进算法或采用其他方法来计算指数函数的更精确值。谢谢您阅读我的问题。
答案 0 :(得分:0)
使用数学库,您可以获得的准确性有限。从文档中:
实施规范的质量涉及两个属性,即返回结果的准确性和方法的单调性。浮点数学方法的精度以单位为ulps的单位表示。对于给定的浮点格式,特定实数值的ulp是包围该数值的两个浮点值之间的距离。当讨论整个方法而不是特定参数的准确性时,引用的ulps数是任何参数下最坏情况的错误。如果某个方法的错误始终小于0.5 ulps,则该方法始终返回最接近精确结果的浮点数;这样的方法是正确的四舍五入。通常,正确舍入的方法最好是浮点近似值。但是,要正确舍入许多浮点方法是不切实际的。相反,对于Math类,某些方法允许更大的错误界限1或2 ulps。非正式地,误差范围为1 ulp,当精确结果为可表示的数字时,应将精确结果作为计算结果返回;否则,可能会返回包含精确结果的两个浮点值之一。为了获得精确的量值,括号的端点之一可以是无限的。除了各个参数的准确性外,在不同参数下保持方法之间的正确关系也很重要。因此,大多数误差大于0.5 ulp的方法都必须是半单调的:每当数学函数不减小时,浮点逼近也是如此,同样,每当数学函数不增大时,浮点逼近也是如此。点近似。并非所有精度为1 ulp的近似值都将自动满足单调性要求。
您可以在docs for the Math class中查看每个计算(方法)的ulp限制。
您可以考虑使用BigDecimals,但是除了一些公开可用的库以外,没有对复杂数学运算的等效支持。 BigDecimals确实允许无限数量的位或精度(在您的计算机内存范围内),但在所有情况下都无法同时提供无限精度和精确结果。如果以无限精度计算1/3,则BigDecimal类将引发错误。有关更多信息,请参见Java BigDecimal trigonometric methods。
答案 1 :(得分:-1)
尝试Apache Commons Math 3.6.1 API