探索 Java 中的複數算術運算
一、簡介
在本教程中,我們將研究複數的算術運算。具體來說,我們將探討如何在 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()) {
// Extract real and imaginary parts
String realPartStr = matcher.group(1);
String imaginaryPartStr = matcher.group(2);
// Parse real part (if present)
double real = (realPartStr != null) ? Double.parseDouble(realPartStr) : 0;
// Parse imaginary part (if present)
double imaginary = (imaginaryPartStr != null) ? Double.parseDouble(imaginaryPartStr) : 0;
return new ComplexNumber(real, imaginary);
} else {
throw new IllegalArgumentException("Invalid complex number format(" + complexNumberStr + "), supported format is `a+bi`");
}
}
public String toString() {
return real + "+" + imaginary + "i";
}
上面的類別定義了複數的實部和虛部。我們使用record
關鍵字來定義表示複數的類別。此外,我們定義了toString()
方法以以a+bi
的典型格式傳回複數。
此外,也重寫了fromString()
方法,以將複數的字串表示形式解析為ComplexNumber
記錄。我們利用正規表示式群組從字串中提取實部和虛部。
在後續部分中,我們可以透過新增執行各種算術運算的方法來增強此記錄。
4. 兩個複數的加法
現在基本設定已準備就緒,讓我們實作兩個複數相加的方法。複數加法是將兩個數的實部和虛部分別相加以獲得結果數。為了提供更清晰的理解,讓我們建立加法公式。讓我們來看看兩個複數相加的公式:
讓我們將這個公式翻譯成 Java 程式碼並將其合併到ComplexNumber
記錄中:
public ComplexNumber add(ComplexNumber that) {
return new ComplexNumber(real + that.real, imaginary + that.imaginary);
}
我們可以直接從記錄中存取實部和虛部,並將它們與方法內給定的複數組合起來。
5. 兩個複數相減
兩個複數相減涉及分別減去它們的實部和虛部。複數a+bi
和c+di
相減時,我們分別減去實部( a
和c
)和虛部( b
和d
),得到一個新的複數,其實部與原實部之差部和虛部作為原虛部的差。這是減法運算的公式:
讓我們用Java來實現減法的方法:
public ComplexNumber subtract(ComplexNumber that) {
return new ComplexNumber(real - that.real, imaginary - that.imaginary);
}
這使用公式(ac)+(bd)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);
}
上述方法實作了複數乘法的演算法。
7. 兩個複數相除
兩個複數的除法甚至比乘法還要複雜。它涉及到一個更複雜的公式:
讓我們將其轉換為 Java 方法:
public ComplexNumber divide(ComplexNumber that) {
if (that.real == 0 && that.imaginary == 0) {
throw new ArithmeticException("Division by 0 is not allowed!");
}
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);
}
上述方法有效地除兩個複數。它包含錯誤處理以防止被零除,並在這種情況下提供清晰的錯誤訊息。
8. 測試實施
現在我們已經實作了兩個複數的算術運算,讓我們為每個方法編寫測試案例。複數可以有多種形式,包括只有實部、只有虛部或兩者兼具的形式。為了確保穩健的實施,我們必須在所有這些場景中徹底測試我們的實作。為了全面覆蓋,我們可以利用 JUnit 的參數化測試來測試不同的輸入。
為了保持本文的簡潔性,我們將重點放在演示複數除法的單一測試案例:
@ParameterizedTest(name = "Dividing {0} and {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));
}<br />public boolean isSame(ComplexNumber result, ComplexNumber expected){<br /> return result.real() == expected.real() && result.imaginary() == expected.imaginary();<br />}
在上面的實作中,我們使用@CsvSource
建立了一個全面的測試套件來涵蓋許多複數除法。實作了自訂實用程式方法isSame(),
以有效比較測試結果。同樣,我們可以使用相同的測試參數來實現其他算術運算的測試。
此外,我們還可以寫一個單獨的測試來驗證被零除的場景:
@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(), "Division by 0 is not allowed!");
}
在這裡,我們建立一個實部和虛部均為零的複數,然後嘗試除以它。使用assertThrows()
,測試可確保拋出例外並附帶預期的錯誤訊息。
9. 結論
在本文中,我們用 Java 實作了兩個複數的算術運算。我們探索了複數的加法、減法、乘法和除法,透過廣泛的測試覆蓋範圍實現了強大的功能。這包括利用參數化測試來確保程式碼在各種輸入值下正確運行。
與往常一樣,本文中使用的範例程式碼可以在 GitHub 上取得。