Like Share Discussion Bookmark Smile

J.J. Huang   2025-01-20   Getting Started Golang 01.基本型別   瀏覽次數:次   DMCA.com Protection Status

Go | 初步了解「複數」型別

💬 簡介

複數型別(Complex Types)是一種特殊的數值型別,主複數是一種由實數部分和虛數部分組成的數字,通常以 a + bi 的形式表示。在 Go 語言中,內建了對複數型別的支持,提供了 complex64complex128 兩種型別。

本篇文章將介紹 Go 語言中複數型別的基本特性、操作方式及應用場景,幫助在數學運算、科學計算及其他需要複數的場景中得心應手地使用。

圖片來源:Gophers(地鼠造型的原創者為 Renee French)


🔎 Go 語言中的複數型別

提供了兩種複數型別,分別為 complex64complex128。它們的區別在於表示實數部分和虛數部分所使用的精度不同。

1️⃣ complex64 與 complex128 比較

  • complex64:實數部分和虛數部分均使用 float32 表示。
  • complex128:實數部分和虛數部分均使用 float64 表示,精度較高。

2️⃣ 宣告與初始化

Go 使用 complex 函式來創建複數,也可以直接使用字面值表示。

  • 範例:複數的宣告與初始化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    package main

    import "fmt"

    func main() {
    var c1 complex64 = 1 + 2i
    c2 := complex(3.5, -4.5)

    fmt.Println("複數 c1:", c1) // 輸出:1+2i
    fmt.Println("複數 c2:", c2) // 輸出:3.5-4.5i
    }

    📝在這個範例中,c1 是使用字面值宣告的複數,c2 則是使用 complex 函式創建的複數。


➕ 複數的基本操作

對複數進行加法、減法、乘法、除法等運算,並提供了標準庫函式來操作複數的實數部分與虛數部分。

1️⃣ 基本運算

  • 範例:複數的運算
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package main

    import "fmt"

    func main() {
    c1 := complex(1, 2)
    c2 := complex(3, -4)

    fmt.Println("加法:", c1+c2) // 輸出:4-2i
    fmt.Println("減法:", c1-c2) // 輸出:-2+6i
    fmt.Println("乘法:", c1*c2) // 輸出:11+2i
    fmt.Println("除法:", c1/c2) // 輸出:約 -0.2+0.4i
    }

    📝在這個範例中,我們進行了複數的加減乘除運算,並輸出結果。

2️⃣ 提取實數與虛數部分

提供了 realimag 函式來分別提取複數的實數部分與虛數部分。

  • 範例:提取實數與虛數部分
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package main

    import "fmt"

    func main() {
    c := complex(5, -7)

    fmt.Println("實數部分:", real(c)) // 輸出:5
    fmt.Println("虛數部分:", imag(c)) // 輸出:-7
    }

    📝在這個範例中,real 函式返回複數的實數部分,imag 函式返回虛數部分。


⚠️ 注意事項

1️⃣ 複數運算的結果

在進行複數運算時,需要注意其結果會依照運算的性質而有所不同,並且可能會涉及到四則運算中的誤差。
例如,複數的除法可能會帶來精度上的問題,這需要特別注意。

  • 範例:複數除法的精度問題
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package main

    import "fmt"

    func main() {
    c1 := complex(3, 4)
    c2 := complex(1, 1)

    // 複數除法
    quot := c1 / c2
    fmt.Println("複數除法結果:", quot) // 輸出:3.5+0.5i
    }

    📝在複數除法的運算中,我們可能會遇到精度損失的情況,這類問題在數值計算中比較常見,特別是在進行大量運算時。

2️⃣ 使用複數型別時的建議

由於複數的運算在某些情況下可能會引起浮點數精度的問題,因此在使用複數型別時,建議使用精度更高的浮點數型別(如 complex128)來儘量減少這些誤差。


🌍 應用場景

複數型別在許多科學、工程及數學領域中都有廣泛的應用,特別是在需要處理涉及波動、旋轉、電壓與電流等現象的情況下。以下是一些典型的應用領域:

⚡ 電路分析與信號處理

在電子學中,複數被用來描述交流電的相位與幅度。例如,交流電的電壓和電流經常使用複數來表示,因為它們涉及到正弦波的相位和頻率。複數使得這些問題的運算變得簡單且直觀。

  • 範例:複數在電路分析中的應用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package main

    import "fmt"

    func main() {
    // 假設有一個電壓 V = 10 + 5i 和電流 I = 3 + 4i
    V := complex(10, 5) // 複數電壓
    I := complex(3, 4) // 複數電流

    // 計算阻抗 Z = V / I
    Z := V / I
    fmt.Println("電路的阻抗 Z:", Z) // 輸出:(2-1i)
    }

    📝在這個範例中,我們使用複數表示電壓和電流,然後計算阻抗。這使得交流電的分析變得更加簡便。

🌀 波動與旋轉運算

複數在物理學中也有重要的應用,特別是在描述波動現象時。波動的運動可以使用複數來簡化,並且利用複數表示波的幅度和相位關係。

例如,物理學中描述光波、聲波等波動現象時,經常會將波的形狀表示為複數。複數可以幫助我們更輕鬆地處理旋轉、變形等現象。

  • 範例:旋轉矩陣與複數的關聯
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    package main

    import (
    "fmt"
    "math"
    "math/cmplx"
    )

    func main() {
    // 旋轉 90 度的複數
    c1 := complex(1, 0) // 初始複數 1 + 0i
    rotation := cmplx.Exp(complex(0, math.Pi/2)) // 使用 math.Pi 旋轉 90 度

    // 旋轉後的複數
    rotated := c1 * rotation

    // 處理誤差,將非常接近 0 的實部視為 0
    if math.Abs(real(rotated)) < 1e-15 {
    rotated = complex(0, imag(rotated))
    }

    fmt.Println("旋轉後的複數:", rotated) // 輸出: (0+1i)
    }

    📝這個範例使用複數來表示旋轉,通過旋轉矩陣將一個數字從初始位置旋轉 90 度,並簡單地得到結果 (0 + 1i)

🖥️ 圖像處理與電腦視覺

複數也在圖像處理中發揮重要作用,特別是在頻域處理中。透過將圖像轉換到頻域(例如傅里葉變換),我們可以利用複數進行圖像的濾波、降噪等操作。

  • 範例:圖像處理中的傅里葉變換
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package main

    import (
    "fmt"
    "math/cmplx"
    )

    func main() {
    // 假設圖像的頻域資料為複數
    freqData := []complex128{
    complex(10, 5), // 頻域資料點
    complex(3, 2),
    complex(7, 1),
    }

    // 輸出每個頻域資料的模和相位
    for _, freq := range freqData {
    fmt.Println("模:", cmplx.Abs(freq), " 相位:", cmplx.Phase(freq))
    }
    }

    📝在這個範例中,我們模擬了圖像的頻域資料,並使用複數計算其模和相位,這在傅里葉變換中是非常重要的。

🎶 音頻處理與數字信號處理

在音頻處理中,複數同樣扮演著關鍵角色,尤其是在數字信號處理(DSP)中。通過使用複數,音頻信號的頻率、相位和幅度能夠更加精確地進行表示與操作。

  • 範例:音頻信號的頻率分析
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package main

    import (
    "fmt"
    "math/cmplx"
    )

    func main() {
    // 假設音頻信號在頻域的表示
    signal := complex(5, 3)

    // 計算其頻率(模)和相位
    fmt.Println("信號的幅度(頻率):", cmplx.Abs(signal))
    fmt.Println("信號的相位:", cmplx.Phase(signal))
    }

    📝這個範例展示了如何使用複數分析音頻信號的幅度與相位,這在音頻信號處理中非常常見。


🎯總結

複數型別是一個強大工具,特別適用於處理涉及實數與虛數的計算。理解複數型別的結構與運算,能幫助更高效地進行數學與科學計算,並解決許多工程問題。

通過學習 Go 中複數的應用,我們能夠在複雜的領域中解決更多問題。

最後建議回顧一下 Go | 菜鳥教學 目錄,了解其章節內容。


註:以上參考了
Go