8

我正在尝试用 C++ 编写一个函数,该函数使用二次方程求解 X。这是我最初写的,只要没有复数作为答案,它似乎就可以工作:

float solution1 = (float)(-1.0 * b) + (sqrt((b * b) - (4 * a * c)));
solution1 = solution1 / (2*a);

cout << "Solution 1: " << solution1 << endl;

float solution2 = (float)(-b) - (sqrt((b*b) - (4 * a * c)));
solution2 = solution2 / (2*a);
cout << "Solution 2: " << solution2;

例如,如果我使用方程:x^2 - x - 6,我会正确地得到解 3, -2。

我的问题是我将如何解释复数....例如,给定等式:

x^2 + 2x + 5

手动求解,我会得到 -1 + 2i,-1 - 2i。

好吧,我猜有两个问题,我可以把上面的写得更好,也可以解释复数吗?

谢谢你的帮助!

4

6 回答 6

22

所有这一切的重要说明。这些回复和原始问题中显示的解决方案并不可靠。

当ac与b^2相比非常小时,众所周知的解决方案(-b +- sqrt(b^2 - 4ac)) / 2a在计算中是非鲁棒的,因为减去两个非常相似的值。对于另一个根,最好使用鲜为人知的解决方案2c / (-b -+ sqrt(b^2 -4ac)) 。

一个稳健的解决方案可以计算为:

temp = -0.5 * (b + sign(b) * sqrt(b*b - 4*a*c);
x1 = temp / a;
x2 = c / temp;

使用 sign(b) 确保我们不会减去两个相似的值。

对于 OP,将其修改为复数,如其他海报所示。

于 2009-05-22T21:44:10.097 回答
7

像这样的东西会起作用:

struct complex { double r,i; }
struct pair<T> { T p1, p2; }

pair<complex> GetResults(double a, double b, double c)
{
  pair<complex> result={0};

  if(a<0.000001)    // ==0
  {
    if(b>0.000001)  // !=0
      result.p1.r=result.p2.r=-c/b;
    else
      if(c>0.00001) throw exception("no solutions");
    return result;
  }

  double delta=b*b-4*a*c;
  if(delta>=0)
  {
    result.p1.r=(-b-sqrt(delta))/2/a;
    result.p2.r=(-b+sqrt(delta))/2/a;
  }
  else
  {
    result.p1.r=result.p2.r=-b/2/a;
    result.p1.i=sqrt(-delta)/2/a;
    result.p2.i=-sqrt(-delta)/2/a;
  }

  return result;
}

这样,您就可以以类似的方式获得真实和复杂结果的结果(真实结果只是将虚部设置为 0)。加了boost会更漂亮!

编辑:修复了 delta 事物并添加了对退化情况的检查,例如 a=0。不眠之夜ftl!

于 2009-05-22T14:26:54.000 回答
4

你或多或少有它,只需检查平方根内的部分是否为负,然后在你的减少中单独跟踪它。

于 2009-05-22T14:16:08.093 回答
3

您基本上可以只使用std::complex<float>而不是float获得对复数的支持。

于 2009-05-22T14:47:42.973 回答
1

从 Blindy 那里得到灵感:

typedef std::complex<double> complex;
using std::pair;
pair<complex> GetResults(double a, double b, double c)
{
  double delta=(b*b-4*a*c);
  double inv_2a = 1/2/a;
  if(delta >= 0) {
    double root = sqrt(delta);
    return std::make_pair(
        complex((-b-root)*inv_2a),
        complex((-b+root)*inv_2a);
  } else {
    double root = sqrt(-delta);
    return std::make_pair(
        complex(-b*inv_2a, -root*inv_2a)),
        complex(-b*inv_2a, +root*inv_2a)));
  }
}
于 2009-05-22T15:05:09.570 回答
-1

我在没有使用“math.h”标头的情况下尝试了该程序,并且还尝试了不同的逻辑......但我的程序只能回答那些具有“x平方”系数的二次方程......并且其中的“x”系数' 可以表示为两个数的加法,这两个数是常数项的因数。例如。x平方+8x+16;x平方+7x+12;等等这里 8=4+4 & 16=4*4; 这里 x 的系数可以表示为两个数的加法,它们是常数项 16 的因数……我自己对此并不完全满意,而是尝试了一些不同的方法,没有使用求解二次方程的公式。代码是;

        #include<iostream.h>
        #include<conio.h>
         class quadratic
              {
                int b,c ;
                float l,k;
                public:
               void solution();
              };
        void quadratic::solution()
             {
                 cout<<"Enter coefficient of x and the constant term of the quadratic eqn where coefficient of x square is one";
                 cin>>b>>c;

                 for(l=1;l<b;l++)
                  {
                   for(k=1;k<b;k++)
                    {
                     if(l+k==b&&l*k==c)
                        {
                          cout<<"x="<<-l<<"\t"<<"or"<<"\t"<<"x="<<-k;
                          cout<<"\n";
                         }
                    }
                }
            }
              void main()
                 {
                  quadratic a;
                   clrscr();
                  a.solution();
                  getch();
                 }
于 2012-11-01T09:13:49.747 回答