Complex
- 数学计算:加减乘除、求模、辐角、平方根、倒数、相反数、共轭复数等
- 其他:字符串转复数
parseComplex()、复数转字符串toString()等
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Complex {
private double real, imag;
public static final Complex REAL_UNIT = new Complex(1.0, 0.0);
public static final Complex NEG_REAL_UNIT = new Complex(-1.0, 0.0);
public static final Complex IMAG_UNIT = new Complex(0.0, 1.0);
public static final Complex NEG_IMAG_UNIT = new Complex(0.0, -1.0);
public static final Complex ZERO = new Complex(0.0);
public Complex(double real, double imag) {
this.real = real;
this.imag = imag;
}
public Complex(double real) {
this.real = real;
this.imag = 0;
}
public Complex() {
this.real = 0;
this.imag = 0;
}
public double real() {
return this.real;
}
public double imag() {
return this.imag;
}
protected void set(double real, double imag) {
this.real = real;
this.imag = imag;
}
protected void setReal(double real) {
this.real = real;
}
protected void setImag(double imag) {
this.imag = imag;
}
@Override
public String toString() {
if (this.imag > 0) {
return ((real==0) ? "" : real+"+") + imag + "i";
} else if (this.imag < 0) {
return ((real==0) ? "" : real+"") + imag + "i";
} else {
return String.valueOf(real);
}
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Complex)) return false;
Complex other = (Complex) obj;
return this.real == other.real && this.imag == other.imag;
}
@Override
public int hashCode() {
return Double.valueOf(this.real).hashCode() ^ Double.valueOf(this.imag).hashCode();
}
public Complex copy() {
return new Complex(this.real, this.imag);
}
public static Complex valueOf(double d) {
return new Complex(d);
}
public static Complex valueOf(String s) {
return parseComplex(s);
}
public static Complex parseComplex(String s) {
double real = 0;
double imag = 0;
final String doubleRegex = "[-+]?(\\d+(\\.\\d*)?|\\.\\d+)([eE]([-+]?([012]?\\d{1,2}|30[0-7])|-3([01]?[4-9]|[012]?[0-3])))?";
final String pureImagRegex = doubleRegex+"[a-zA-Z]";
final String complexRegex1 = "(?<real>"+doubleRegex+")" + "(?<imag>"+doubleRegex+")" + "[a-zA-Z]";
final String complexRegex2 = "(?<imag>"+doubleRegex+")" + "[a-zA-Z]" + "(?<real>"+doubleRegex+")";
if (Pattern.compile(doubleRegex).matcher(s).matches()) {
real = Double.parseDouble(s);
} else if (Pattern.compile(pureImagRegex).matcher(s).matches()) {
imag = Double.parseDouble(s.substring(0, s.length()-1));
} else {
Matcher matcher = Pattern.compile(complexRegex1).matcher(s);
if (matcher.matches()) {
real = Double.parseDouble(matcher.group("real"));
imag = Double.parseDouble(matcher.group("imag"));
} else {
matcher = Pattern.compile(complexRegex2).matcher(s);
if(matcher.matches()) {
real = Double.parseDouble(matcher.group("real"));
imag = Double.parseDouble(matcher.group("imag"));
} else {
throw new NumberFormatException("\""+ s + "\" can't be translated as a complex.");
}
}
}
return new Complex(real, imag);
}
public boolean eq(Complex complex) {
return Math.abs(real-complex.real)+Math.abs(imag-complex.imag) < 1e-6;
}
public Complex add(Complex augend) {
return new Complex(this.real+augend.real, this.imag+augend.imag);
}
public Complex add(double real) {
return new Complex(this.real+real, this.imag);
}
public Complex sub(Complex subtrahend) {
return new Complex(this.real-subtrahend.real, this.imag-subtrahend.imag);
}
public Complex sub(double real) {
return new Complex(this.real-real, this.imag);
}
public Complex mul(Complex multiplicand) {
double real = this.real*multiplicand.real - this.imag*multiplicand.imag;
double imag = this.real*multiplicand.imag + this.imag*multiplicand.real;
return new Complex(real, imag);
}
public Complex mul(double real) {
return new Complex(this.real*real, this.imag*real);
}
public Complex div(Complex divisor) {
double denominator = divisor.real*divisor.real + divisor.imag*divisor.imag;
if (denominator == 0) {
throw new ArithmeticException("Complex division by zero!");
}
double real = (this.real*divisor.real + this.imag*divisor.imag) / denominator;
double imag = (this.imag*divisor.real - this.real*divisor.imag) / denominator;
return new Complex(real, imag);
}
public Complex div(double real) {
if (real == 0) {
throw new ArithmeticException("Complex division by zero!");
}
return new Complex(this.real/real, this.imag/real);
}
public double abs() {
return Math.sqrt(real*real + imag*imag);
}
public double mod() {
return Math.sqrt(real*real + imag*imag);
}
public double arg() {
return Math.atan2(this.imag, this.real);
}
public Complex inv() {
double denominator = real*real + imag*imag;
if (denominator == 0) {
throw new ArithmeticException("ZERO has no inverse!");
}
double real = this.real / denominator;
double imag = this.imag / denominator;
return new Complex(real, imag);
}
public Complex neg() {
return new Complex(-this.real, -this.imag);
}
public Complex conj() {
return new Complex(this.real, -this.imag);
}
public Complex sqrt() {
double mod = this.mod();
double sqrt2 = Math.sqrt(2);
double real = Math.sqrt(mod + this.real) / sqrt2;
double sgn = Math.signum(this.imag);
if (sgn == 0.0) {
sgn = 1.0;
}
double imag = Math.sqrt(mod - this.real) / sqrt2 * Math.signum(sgn);
return new Complex(real, imag);
}
public boolean isZero() {
return this.real == 0 && this.imag == 0;
}
public boolean isReal() {
return this.imag == 0;
}
public boolean isImag() {
return this.real == 0;
}
}
ComplexTest
public class ComplexTest {
private static final double delta = 1e-6;
@Test
public void testToString() {
Complex complex1 = new Complex(2, -3);
Complex complex2 = new Complex(2.5, 3.9);
Complex complex3 = new Complex(0, -0.8);
Complex complex4 = new Complex(1);
Complex complex5 = new Complex(0, 0.8);
Complex complex6 = Complex.ZERO;
System.out.println(complex1);
System.out.println(complex2);
System.out.println(complex3);
System.out.println(complex4);
System.out.println(complex5);
System.out.println(complex6);
}
@Test
public void testDiv() {
Complex complex1 = new Complex(10, -10);
Complex complex2 = new Complex(3, 4);
Complex res = complex1.div(complex2);
System.out.println(res);
Assert.assertTrue(res.eq(new Complex(-0.4, -2.8)));
try {
complex1.div(Complex.ZERO);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
@Test
public void testSqrt() {
Complex complex1 = new Complex(4);
Assert.assertTrue(complex1.sqrt().eq(new Complex(2)));
Complex complex2 = new Complex(1, 4);
Complex sqrt = complex2.sqrt();
System.out.println(sqrt);
Complex mul = sqrt.mul(sqrt);
System.out.println(mul);
Assert.assertTrue(complex2.eq(mul));
}
@Test
public void testArg() {
Complex complex = new Complex(1, 1);
double angel = complex.arg();
System.out.println(complex.arg());
Assert.assertEquals(complex.arg()*4, Math.PI, delta);
}
@Test
public void testParseComplex() {
Complex complex1 = Complex.parseComplex("1+5i");
Complex complex2 = Complex.parseComplex("12.j+5");
Complex complex3 = Complex.parseComplex("1e-3-2e3i");
Complex complex4 = Complex.parseComplex("0+1.j");
Complex complex5 = Complex.parseComplex(".5");
System.out.println(complex1);
System.out.println(complex2);
System.out.println(complex3);
System.out.println(complex4);
System.out.println(complex5);
try {
Complex.parseComplex("0.2+ 3j");
} catch (NumberFormatException e) {
e.printStackTrace();
}
try {
Complex.parseComplex("0.2+3ja");
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}