目录
一、复数类的生成
1、初始化复数
2、生成以及提取复数的相关方法
3、复数的显示
二、复数的相关运算
1、加法(Add)
2、减法(Sub)
3、乘法(Mul)
4、除法(Div)
5、复数的相等比较
三、测试程序及总结
1、测试
2、总结
一、复数类的生成
1、初始化复数
我们首先需要初始化一个新的复数,以便我们之后进行复数的运算。所以我们定义复数的实部和虚部为double 类型的real和vir,且由于我们作为一个复数类工具,我们并不希望工具内的成员不可以被类外的对象所引用,故二者的访问方式均为private。
接下来我们需要编写复数类的构造方法,为了可以适应对象使用不同的参数来调用构造方法,我们需要对构造方法进行重载。形成无参构造、单参构造、双参构造以及参数为对象的构造共四种构造方法。代码如下所示
private double real;
private double vir;
public Complex() {
this(0.0, 0.0);
}
public Complex(double real, double vir) {
this.real = real;
this.vir = vir;
}
public Complex(double real) {
this(real, 0.0);
}
public Complex(Complex c) {
this(c.real, c.vir);
}
2、生成以及提取复数的相关方法
由于我们需要将复数的实部与虚部作为private变量保护起来,故需要编写一系列可以在类外提取与改变实部与虚部的相关方法。编写这些方法存在一个简单的生成方法,如果使用eclipse编程的话便可以调用Source中的Generate Getters and Setters方法便可生成getReal() 、setReal() 、getVir() 和setVir() 四种方法。如下所示:
public double getReal() {
return real;
}
public void setReal(double real) {
this.real = real;
}
public double getVir() {
return vir;
}
public void setVir(double vir) {
this.vir = vir;
}
3、复数的显示
由于复数的形式为A + Bi,故我们需要重载Object的toString方法,生成一个String类型的符号,如果虚部为复数的话,则实部与虚部间不需要符号链接,否则加上符号“+”。
@Override
public String toString() {
String sign = new String();
if(this.vir > 0) {
sign = "+";
}
return "(" + real + sign + vir + "i)";
}
二、复数的相关运算
1、加法(Add)
复数的加法运算有两种形式:
1.c3 = c1 + c2;
2.c1 += c2;
我们需要以方法重载的方式分别实现二者,对于第一种方法我们以对象来调用单参方法且相加的结果再赋值给对象本身,最后方法返回值为对象。代码如下:
public Complex add(Complex other) {
this.real += other.real;
this.vir += other.vir;
return this;
}
而对于第二种方法,我开始使用了很蠢的方法来实现重复了第一种方法中的很多代码(垃圾代码在注释中显示),在对于Java的代码复用了解后,改变了思路调用了原有方法,使得代码变得极为精炼,如下所示:
public static Complex add(Complex one, Complex other) {
return new Complex(one).add(other);
// Complex result = new Complex();
// result.real = one.real + other.real;
// result.vir = one.vir + other.vir;
// return result;
}
仅仅使用一行代码便实现了两个实例的加法运算 ,而使用static静态存储原因在于调用此方法的对象没有任何操作,故直接以静态方法实现,以类名直接调用此方法,提高了代码的可读性以及精炼性。
2、减法(Sub)
对于减法,和加法一样存在两种实现方法。且减法可以通过将被减数变为原来的相反数来转为加法,进行代码复用。故我们需要编写一个仅仅提供给类内部使用的求相反数方法。
private static Complex opposite(Complex c) {
return new Complex(-c.real, -c.vir);
}
之后便通过调用add()方法来实现:
public Complex sub(Complex other) {
return this.add(opposite(other));
}
public static Complex sub(Complex one, Complex other) {
return new Complex(one).add(opposite(other));
}
3、乘法(Mul)
乘法同加法一样通过两种方式实现,对于乘法存在一个this.real的值会在求新的this.real中发生改变,故我们需要定义一个double类型的tmp变量来临时存储this.real的值。方法实现如下:
public Complex mul(Complex c) {
double tmp = this.real;
this.real = tmp * c.real - this.vir * c.vir;
this.vir = tmp * c.vir + c.real * this.vir;
return this;
}
public static Complex mul(Complex one, Complex other) {
return new Complex(one).mul(other);
}
4、除法(Div)
与前面相同,除法同样可以使用乘法来实现,复数相除即前者乘以后者的倒数。故分析复数的倒数实现方式——(a + bi) => (a - bi) / (a+bi) * (a-bi) => (a-bi) / (a*a + b*b)。代码如下:
private static Complex reciprocal(Complex c ) {
double model = c.real * c.real + c.vir * c.vir;
if (Math.abs(model) <= 1e-6) {
throw new ArithmeticException("除0错 !");//这里是Java的错误处理机制
}
return new Complex(c.real / model, -c.vir / model);
}
public Complex div(Complex c) {
return this.mul(reciprocal(c));
}
public static Complex div(Complex one, Complex other) {
return new Complex(one).mul(reciprocal(other));
}
5、复数的相等比较
由于复数比较特殊我们需要考虑它的相等比较,故我们可以重载Object的equals方法。重载如下所示,针对不同情况给出不同的判断方法来做到真正相等比较两个复数。
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (!getClass().equals(obj.getClass())) {
return false;
}
Complex tmp = (Complex) obj;
return Math.abs(this.real - tmp.real) <= 1e-6
&& Math.abs(this.vir - tmp.vir) <= 1e-6;
}
三、测试程序及总结
1、测试
测试代码如下,以便我们进行检验,故数字采取较简单。
package com.mec.complex.test;
import com.mec.complex.core.Complex;
public abstract class Test {
public static void main(String[] args) {
Complex c1 = new Complex(3.4, -1.2);
Complex c2 = new Complex(25.0, 25.0);
Complex c3 = new Complex(3.0, 4.0);
Complex c4 = new Complex(25.0,25.0);
//Add
//c1.add(c3);
//System.out.println(c1);
c1.add(c2).add(c3);
System.out.println("Add :"+ c1);
//Sub
c2.sub(c3);
System.out.println("Sub :"+ c2);
//Mul
Complex c5 = Complex.mul(c4, c3);
System.out.println("Mul :" + c5);
//Div
c4.div(c3);
System.out.println("Div :" + c4);
}
}
运行结果如下:
,可得正确实现了复数类。
2、总结
对于复数类的实现过程中存在几个比较不错的点:
1、对于代码复用的简单使用,使得程序更加简练。
2、对于静态存储变量的实际应用,使程序的可读性更高。
3、对于工具的保护思想需要牢记。
4、方法返回值为对象本身可以在实际调用时使用链式调用,更加便捷,且不同方法的重 载与覆盖都是需要我们好好学习,并加以运用的点。