试图划分复数,除以零

时间:2011-01-05 02:31:54

标签: c complex-numbers divide-by-zero

我正在尝试下面的程序来划分复数,它适用于复数,但不适用于分母是实数(即复数部分为零)。当复数部分ratio = b->r / b->i ;为零时(在真实分母的情况下),此行b->i中会出现除零。

我如何解决这个问题?为什么程序员会这样做,而不是complex division

更直接的规则

维基百科规则似乎更好,此处不会出现除零错误。我错过了什么?为什么程序员不使用维基百科公式??

由于

/*! @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;
}

3 个答案:

答案 0 :(得分:1)

在我看来,原始程序员确保ratio最终会介于0和1(包括)之间,以确保维持足够的精确度。

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

另据我所知,以下测试:

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

只有在abiabr都为零的情况下才能为真,因此您将处于真正的零除状态。

(此时abiabr都被强制为非负数,并且该代码路径仅在(abr <= abi))时被点击。

也许你可以张贴一个小的测试用例,显示当r非零时点击被零除。

答案 1 :(得分:0)

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

答案 2 :(得分:-1)

如果大家第一次完美地写下了所有内容,那么我的猜测很多就是失业。

使用其他人代码始终存在遇到此类问题的风险。出于这个原因,我会使用像Apache implementation (std::complex)这样的东西。他们的大多数东西都很好地保存和审查。