簡體   English   中英

如何比較兩個復數?

[英]How to compare two complex numbers?

在C中,復數是浮點數或雙精度數,並且與規范類型具有相同的問題:

#include <stdio.h>
#include <complex.h>

int main(void)
{
    double complex a = 0 + I * 0;
    double complex b = 1 + I * 1;

    for (int i = 0; i < 10; i++) {
        a += .1 + I * .1;
    }

    if (a == b) {
        puts("Ok");
    }
    else {
        printf("Fail: %f + i%f != %f + i%f\n", creal(a), cimag(a), creal(b), cimag(b));
    }

    return 0;
}

結果:

$ clang main.c
$ ./a.out 
Fail: 1.000000 + i1.000000 != 1.000000 + i1.000000

我試試這個語法:

a - b < DBL_EPSILON + I * DBL_EPSILON

但編譯器討厭它:

main.c:24:15: error: invalid operands to binary expression ('_Complex double' and '_Complex double')
    if (a - b < DBL_EPSILON + I * DBL_EPSILON) {
        ~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

這最后工作正常,但它有點挑剔:

fabs(creal(a) - creal(b)) < DBL_EPSILON && fabs(cimag(a) - cimag(b)) < DBL_EPSILON

您可以計算其差值的復數絕對值(也稱為范數模數幅度 ),而不是比較復數分量,即復平面上兩者之間的距離:

if (cabs(a - b) < DBL_EPSILON) {
    // complex numbers are close
}

即使沒有精度問題,小的復數也會接近零,這個問題也存在於實數中。

比較2個復數浮點數非常類似於比較2個實數浮點數。

比較精確等價通常是不夠的,因為涉及的數字包含小的計算錯誤。

所以而不是if (a == b)代碼需要if (nearlyequal(a,b))


通常的方法是double diff = cabs(a - b) ,然后將diff與一些小的常量值diff ,如DBL_EPSILON

a,b為大數時a,b這會失敗 a,b因為它們的差異可能比DBL_EPSILON大許多個數量級,即使a,b僅與它們的最低有效位不同。

對於小數字也是如此,因為a,b之間的差異可能相對較大,但是比DBL_EPSILON小許多個數量級,因此當值相對完全不同時返回true

復數實際上在問題上增加了另一個維度問題,因為實部和虛部本身可能會有很大不同。 因此, nearlyequal(a,b)的最佳答案高度依賴於代碼的目標。


為簡單起見,讓我們使用差異的大小與a,b的平均大小進行比較。 控制常數ULP_N近似於允許a,b不同的最小重要性的二進制數字的數量。

#define ULP_N 4

bool nearlyequal(complex double a, complex double b) {
  double diff = cabs(a - b);
  double mag = (cabs(a) + cabs(b))/2;
  return diff <= (mag * DBL_EPSILON * (1ull << ULP_N));
}

由於復數表示為浮點數,因此必須處理它們固有的不精確性 如果浮點數位於機器epsilon內,則它們“足夠接近”。

通常的方法是減去它們,取絕對值,然后看它是否足夠接近。

#include <complex.h>
#include <stdbool.h>
#include <float.h>

static inline bool ceq(double complex a, double complex b) {
    return cabs(a-b) < DBL_EPSILON;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM