2

我正在尝试下面的程序来划分复数,它适用于复数,但当分母为实数时(即复数部分为零)则无效。ratio = b->r / b->i ;当复数部分b->i为零时(在实分母的情况下) ,在这一行中除以零。

我该如何解决这个问题?以及为什么程序员这样做,而不是更直接的复杂除法规则

维基百科的规则似乎更好,这里不会发生除以零错误。我错过了什么?为什么程序员不使用维基百科公式?

谢谢

/*! @file dcomplex.c
 * \brief Common arithmetic for complex type
 *
 * <pre>
 * -- SuperLU routine (version 2.0) --
 * Univ. of California Berkeley, Xerox Palo Alto Research Center,
 * and Lawrence Berkeley National Lab.
 * November 15, 1997
 *
 * This file defines common arithmetic operations for complex type.
 * </pre>
 */

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include "slu_dcomplex.h"


/*! \brief Complex Division c = a/b */
void z_div(doublecomplex *c, doublecomplex *a, doublecomplex *b)
{
    double ratio, den;
    double abr, abi, cr, ci;

    if( (abr = b->r) < 0.)
        abr = - abr;
    if( (abi = b->i) < 0.)
         abi = - abi;
    if( abr <= abi ) {
        if (abi == 0) {
            fprintf(stderr, "z_div.c: division by zero\n");
            exit(-1);
        }   
        ratio = b->r / b->i ;
        den = b->i * (1 + ratio*ratio);
        cr = (a->r*ratio + a->i) / den;
        ci = (a->i*ratio - a->r) / den;
    } else {
        ratio = b->i / b->r ;
        den = b->r * (1 + ratio*ratio);
        cr = (a->r + a->i*ratio) / den;
        ci = (a->i - a->r*ratio) / den;
    }
    c->r = cr;
    c->i = ci;
}
4

3 回答 3

1

在我看来,最初的程序员正在确保ratio最终会在 0 和 1(含)之间,以确保保持足够的精度。

维基百科上的算法的直接编码看起来会有获得一些非常大的除数的危险。

另外,据我所知,以下测试:

   if (abi == 0) {
        fprintf(stderr, "z_div.c: division by zero\n");
        exit(-1);
   }   

abi仅当和都为零时才为真abr,因此您将处于实际除以零的情况。

(那时,abi两者abr都被迫为非负数,并且该代码路径仅在 时被命中(abr <= abi))。

也许您可以发布一个小测试用例,显示在非零时r被零除。

于 2011-01-05T02:57:36.747 回答
0

你必须使用这个库吗?C99 有一个complex类型。

于 2011-01-05T02:49:19.223 回答
-1

如果每个人第一次都写得很完美,那么我猜我们中的很多人都会失业。

使用其他人的代码总是存在遇到此类问题的风险。出于这个原因,我建议使用Apache implementation (std::complex)之类的东西。他们的大部分东西都保存完好并经过审查。

于 2011-01-05T02:39:04.263 回答