尝试除复数,除以零
我正在尝试下面的程序来除复数,它适用于复数,但不适用于分母为实数(即复数部分为零)的情况。当复数部分 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;
}
I'm trying the program below to divide complex numbers, it works for complex numbers but not when the denominator is real (i.e, the complex part is zero). Division by zero occurs in this line ratio = b->r / b->i ;
, when the complex part b->i
is zero (in the case of a real denominator).
How do I get around this? and why did the programmer do this, instead of the more straightforward rule for complex division
The wikipedia rule seems to be better, and no division by zero error would occur here. Did I miss something? Why did the programmer not use the wikipedia formula??
Thanks
/*! @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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在我看来,最初的程序员正在确保
ratio
最终在 0 和 1(含)之间,可能是为了确保保持足够的精度。维基百科上的算法的直接编码看起来可能会有得到一些非常大的除数的危险。
另外,据我所知,以下测试:
仅当 abi 和 abr 都为零时才为真,因此您将处于真正被零除的情况。
(此时
abi
和abr
都被强制为非负数,并且该代码路径仅在(abr <= abi)< 时被命中/代码>)。
也许您可以发布一个小测试用例,显示当 r 不为零时被零除的情况。
Looks to me like the original programmer was ensuring that
ratio
would end up between 0 and 1 (inclusive) probably to ensure that adequate precision was maintained.A straight forward coding of the algorithm on Wikipedia looks like would have danger of getting some very large divisors.
Also, as far as I can tell, the following test:
can only be true if both
abi
andabr
are zero, so you would be in a real divide by zero situation.(At that point
abi
andabr
have both been forced to be non-negative, and that code path only gets hit when(abr <= abi)
).Perhaps you can post a small test case that shows the divide-by-zero being hit when
r
is non-zero.你必须使用这个库吗? C99 有一个
complex
类型。Do you have to use this library? C99 has a
complex
type.如果每个人第一次都写得很完美,那么我猜我们很多人都会失业。
使用他人的代码总是存在遇到此类问题的风险。因此,我建议使用类似 Apache 实现 (std::complex )。他们的大部分东西都保存得很好并且经过审查。
If everyone wrote everything perfectly the first time then my guess is a lot of us would be jobless.
Using another persons code always carries the risk of running into issues like this. For that reason, I'd sugest using something like an Apache implementation (std::complex). Most of their stuff is pretty well kept and vetted.