【问题标题】:trying to divide complex numbers, division by zero试图除以复数,除以零
【发布时间】:2011-01-05 02:31:54
【问题描述】:

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

【问题讨论】:

  • 询问程序员。不仅如此,只需使用std::complex
  • @Gman。它是一个 C 程序。请参阅评论的标题,即 dcomplex.c。 Op 应该删除 c++ 标签
  • 我相信这里可能存在边缘案例错误。老实说,似乎程序员并不是真正的数学家,这没有任何意义。 PS 我同意汤姆的观点。
  • @Tom:哦,我发誓它是 C++...(哦,原来如此。阅读标签,我在想什么。)
  • 这是伯克利的 SuperLU 矩阵求解器,我想是在 1997 年开发的。我想一个错误不会持续那么久。

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


【解决方案1】:

在我看来,最初的程序员确保 ratio 最终会介于 0 和 1(含)之间,可能是为了确保保持足够的精度。

在 Wikipedia 上对算法进行直接编码看起来会有得到一些非常大的除数的危险。

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

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

只有当abiabr 都为零时才能为真,因此您将处于真正的除以零的情况。

(此时abiabr 都被强制为非负数,并且该代码路径只有在(abr &lt;= abi) 时才会被命中)。

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

【讨论】:

  • 嗯,其实我认为你是对的。这些是绝对值,因此 abr 也必须为零,因此是真实除以零的情况。大吃一惊!! (谢谢指出,我想问题就解决了)
  • 再次感谢。那么问题肯定出在其他地方,回到寻找它。
  • 呸!上次我在尝试回答与浮点有关的问题时犯了一个错误(这几乎总是比第一眼看起来更棘手),我发布了一些非常尴尬的内容。
【解决方案2】:

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

【讨论】:

  • 我想使用这个库,它是我的教授想要使用的 SuperLU 矩阵求解器包的一部分
【解决方案3】:

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

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

【讨论】:

  • std::complex 包含在 C++ STL 中。 Apache 页面只解释了它的用法。
  • 另外,他似乎想使用纯C。然后他必须自己实现它,或者如果编译器支持C99,则使用_Complex。
  • 顺便谢谢大家的帮助,非常感谢。奇怪的是为什么程序员会选择所有这些箍。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
  • 2013-02-23
  • 1970-01-01
  • 1970-01-01
  • 2010-10-16
相关资源
最近更新 更多