1. 引言

本教程将深入探讨复数的算术运算。我们具体研究如何在 Java 中实现两个复数的加法、减法、乘法和除法操作。

2. 什么是复数?

复数由实部和虚部组合表示,通常写作 a+bi 的形式。其中 a 和 b 是实数,i 是虚数单位,等同于 -1 的平方根。在数学表达中:

  • a 是复数的实部
  • bi 是虚部

复数虽然对初学者可能显得抽象,但在物理学、数学等实际应用中至关重要,包括量子力学、信号处理和经济学等领域。

与实数类似,复数也能执行加、减、乘、除等算术运算。由于涉及实部与虚部的组合,复数运算会引入复杂度,但每种操作都有特定的公式确保计算准确。

3. 基础设置

在实现复数运算前,我们先构建基础代码框架。首先定义复数表示类:

public record ComplexNumber(double real, double imaginary) {
    public static ComplexNumber fromString(String complexNumberStr) {
        Pattern pattern = Pattern.compile("(-?\\d*\\.?\\d+)?(?:([+-]?\\d*\\.?\\d+)i)?");
        Matcher matcher = pattern.matcher(complexNumberStr.replaceAll("\\s", ""));
        if (matcher.matches()) {
            // 提取实部和虚部
            String realPartStr = matcher.group(1);
            String imaginaryPartStr = matcher.group(2);
            // 解析实部(若存在)
            double real = (realPartStr != null) ? Double.parseDouble(realPartStr) : 0;
            // 解析虚部(若存在)
            double imaginary = (imaginaryPartStr != null) ? Double.parseDouble(imaginaryPartStr) : 0;
            return new ComplexNumber(real, imaginary);
        } else {
            throw new IllegalArgumentException("无效的复数格式(" + complexNumberStr + "),支持格式为 `a+bi`");
        }
    }
    public String toString() {
        return real + "+" + imaginary + "i";
    }
}

这个类使用 Java 的 record 关键字定义复数结构,包含:

  • real:实部
  • imaginary:虚部

关键方法说明:

  • toString():将复数格式化为 a+bi 的标准形式
  • fromString():通过正则表达式解析字符串,提取实部和虚部(支持空格和可选符号)

后续我们将在这个类中添加算术运算方法。

4. 复数加法

复数加法需分别对实部和虚部进行相加。先看数学公式:

复数加法公式

Java 实现非常直观:

public ComplexNumber add(ComplexNumber that) {
    return new ComplexNumber(real + that.real, imaginary + that.imaginary);
}

直接访问两个复数的实部和虚部,分别求和后返回新复数对象。

5. 复数减法

复数减法需分别对实部和虚部进行相减。数学公式如下:

复数减法公式

Java 实现代码:

public ComplexNumber subtract(ComplexNumber that) {
    return new ComplexNumber(real - that.real, imaginary - that.imaginary);
}

本质是分别计算实部差值和虚部差值,公式对应 (a-c)+(b-d)i。

6. 复数乘法

乘法运算比加减法复杂,需要应用分配律和虚数单位特性。数学公式:

复数乘法公式

Java 实现需注意交叉项计算:

public ComplexNumber multiply(ComplexNumber that) {
    double newReal = this.real * that.real - this.imaginary * that.imaginary;
    double newImaginary = this.real * that.imaginary + this.imaginary * that.real;
    return new ComplexNumber(newReal, newImaginary);
}

关键点:

  • 实部计算:实部1*实部2 - 虚部1*虚部2
  • 虚部计算:实部1*虚部2 + 虚部1*实部2

7. 复数除法

除法是复数运算中最复杂的操作,需要通过有理化分母实现。数学公式:

复数除法公式

Java 实现需处理分母为零的情况:

public ComplexNumber divide(ComplexNumber that) {
    if (that.real == 0 && that.imaginary == 0) {
        throw new ArithmeticException("禁止除以零!");
    }
    double c2d2 = Math.pow(that.real, 2) + Math.pow(that.imaginary, 2);
    double newReal = (this.real * that.real + this.imaginary * that.imaginary) / c2d2;
    double newImaginary = (this.imaginary * that.real - this.real * that.imaginary) / c2d2;
    return new ComplexNumber(newReal, newImaginary);
}

实现要点:

  • ✅ 先检查除数是否为 0+0i(零复数)
  • 计算分母 c²+d²(避免重复计算)
  • 分子部分按公式展开计算
  • 最终结果实部/虚部分别除以分母

8. 测试实现

为验证算术运算的正确性,需编写全面的测试用例。复数存在多种形态

  • 纯实数(如 2)
  • 纯虚数(如 4i)
  • 标准复数(如 3+2i)

使用 JUnit 参数化测试覆盖所有场景。以除法测试为例:

@ParameterizedTest(name = "计算 {0} ÷ {1}")
@CsvSource({
    "3+2i, 1+7i, 0.34-0.38i",
    "2, 4, 0.5",
    "2, 4i, 0-0.5i",
    "1+1i, 1+1i, 1",
    "3 +   2i, 1  +   7i, 0.34-0.38i",
    "0+5i, 3+0i, 0+1.6666666666666667i",
    "0+0i, -2+0i, 0+0i",
    "-3+2i, 1-7i, -0.34-0.38i",
    "2+4i, 1, 2+4i"
})
public void givenTwoComplexNumbers_divideThemAndGetResult(String complexStr1, String complexStr2, String expectedStr) {
    ComplexNumber complex1 = ComplexNumber.fromString(complexStr1);
    ComplexNumber complex2 = ComplexNumber.fromString(complexStr2);
    ComplexNumber expected = ComplexNumber.fromString(expectedStr);
    ComplexNumber sum = complex1.divide(complex2);
    Assertions.assertTrue(isSame(sum, expected));
}

public boolean isSame(ComplexNumber result, ComplexNumber expected){
    return result.real() == expected.real() && result.imaginary() == expected.imaginary();
}

测试特点:

  • 使用 @CsvSource 覆盖 9 种典型除法场景
  • 自定义 isSame() 方法比较复数(避免浮点数精度问题)
  • 支持带空格的输入(如 "3 + 2i")

除零异常的单独测试:

@Test
public void givenAComplexNumberAsZero_handleDivideByZeroScenario() {
    ComplexNumber complex1 = new ComplexNumber(1, 1);
    ComplexNumber zero = new ComplexNumber(0, 0);
    Exception exception = Assertions.assertThrows(ArithmeticException.class, () -> {
        complex1.divide(zero);
    });
    Assertions.assertEquals(exception.getMessage(), "禁止除以零!");
}

9. 总结

本文完整实现了 Java 中复数的四则运算:

  • ✅ 加法/减法:实部虚部分别运算
  • ⚠️ 乘法:需处理虚数单位特性
  • ❌ 除法:最复杂,需有理化分母并处理除零异常

通过参数化测试覆盖了多种复数形态,确保代码健壮性。完整实现代码可在 GitHub 获取。


原始标题:Exploring Complex Number Arithmetic Operations in Java