如何从带有形式参数的布尔函数返回值?

时间:2019-10-09 06:39:02

标签: c++

int Solve(double& root1,double& root2) //this is function in the class Eq2
{
    int discrimant = b*b - 4*a*c;
    if(discriminant<0)
    return false;
    else if(discriminant>0)
    {
    root1 = (-b - sqrt(discriminant))/(2*a);
    root2 = (-b + sqrt(discriminant))/(2*a);
    return root1;    //must return root1 and root2
    }
}

int main()
{
Eq2 eq1(1, -5, 6);   //discriminant=1,root1=2,root2=3
Eq2 eq2(1, -6, 8);   //discriminant=4,root1=2,root2=4
Eq2 eq3(1, 2, 3);
Eq2 eq4(0, 0, 0);

double root1, root2;
Eq2 eqq[4] = { eq1,eq2,eq3,eq4 };
for (int i = 0; i < 4; i++)
{
    eqq[i].print();
}
cout << "The roots of the equation are:"<<eq1.Solve(root1,root2);   //here 
i call the function

system("pause");
return 0; 
}

我使函数int起作用了,但是我只能输出1个root。我需要返回root1和root2。谢谢大家的帮助!我仍处于起步阶段,我还有很多东西要学习。

5 个答案:

答案 0 :(得分:4)

免责声明:

在编写我自己的MCVE时,OP编辑了问题。因此,我的标识符有些不同。我希望这不会引起混乱...

Discriminant是一个非常特殊的词,我立刻想起了我在数学中学到的。其余的丢失了,但立即从Wikipedia和google找到的其他内容中刷新了。

OP的实际问题似乎在于了解如何使用reference parameters来从函数中返回值而不使用(或不使用)return。恕我直言,其他答案已经对此进行了介绍。

因此,我专注于演示这一点。

因此,我注意到了一些应考虑的其他问题。

  1. std::sqrt仅应以值≥0调用。
  

如果参数小于-0,则引发FE_INVALID并返回NaN。

  1. 应检查除以0。

  2. (由于我的同事Dipl.-Math的暗示。)由于值很小,所以除法的结果变得不可信任。

由于通常的舍入问题,将浮点值与常量进行比较通常是一个坏主意。因此,我介绍了eps –一点点补偿的epsilon值。

示例代码:

#include <cmath>
#include <iostream>

struct Quad {
  double a, b, c;
  Quad(double a, double b, double c): a(a), b(b), c(c) { }
  Quad(const Quad&) = default;
  Quad& operator=(const Quad&) = default;
  ~Quad() = default;

  bool solve(double &root1, double &root2) const;
};

std::ostream& operator<<(std::ostream &out, const Quad &quad)
{
  return out << quad.a << "x² + " << quad.b << "x + " << quad.c;
}

static double eps = 1E-10;

/* tries to solve the roots of this quadratic function.
 *
 * return: true (solution exists)
 *         root1 and root2 contain results
 *         false (no solution)
 *         root1 and root2 are indeterminate (unchanged)
 */
bool Quad::solve(double &root1, double &root2) const
{
  double discriminant = b * b - 4 * a * c;
  if (discriminant < 0.0) return false; // square root of a negative!
  if (std::abs(a) < eps) return false; // division by 0! (or close to 0)
  root1 = (-b - std::sqrt(discriminant)) / (2 * a);
  root2 = (-b + std::sqrt(discriminant)) / (2 * a);
  return true;
}

int main()
{
  double root1, root2; // declared but not yet initialized
  Quad quad1(-1, 0, 1); // two solutions
  std::cout << "Roots for " << quad1 << ": ";
  if (!quad1.solve(root1, root2)) std::cout << "none\n";
  else std::cout << root1 << ", " << root2 << '\n';
  Quad quad2(1, -4, 4); // one solution
  std::cout << "Roots for " << quad2 << ": ";
  if (!quad2.solve(root1, root2)) std::cout << "none\n";
  else std::cout << root1 << ", " << root2 << '\n';
  Quad quad3(1, 0, 2); // no solution
  std::cout << "Roots for " << quad3 << ": ";
  if (!quad3.solve(root1, root2)) std::cout << "none\n";
  else std::cout << root1 << ", " << root2 << '\n';
}

输出:

Roots for -1x² + 0x + 1: 1, -1
Roots for 1x² + -4x + 4: 2, 2
Roots for 1x² + 0x + 2: none

Live Demo on coliru

诀窍在于,Quad::solve()返回truefalse(如所记录),并在前一种情况下更新变量root1root2,但不更新后者。

以不太紧凑的形式编写:

  bool valid = quad1.solve(root1, root2);
  if (valid) { // root1, root2 updated
    std::cout << root1 << ", " << root2 << '\n';
  } else { // no result computed -> root1, root2 not updated
    std::cout << "none\n";
  }

我从这个German site中提取了样本值。

Samples from de.serlo.org

答案 1 :(得分:2)

对于返回类型应该是什么存在一些争论,我认为intbool更好,因为您可能要发出三种不同的返回方案(无根,单根和两个根)。您可以辩称,可以通过在调用方中进行root1 == root2比较来区分后两者,但是如果必须返回成功值,为什么不让它能够表达所有选项。

所以我的答案应该是这样的:

int Solve(double& root1, double& root2)
{
    int discriminant = b * b - 4 * a * c;
    if (discriminant < 0)  // No roots
        return 0;
    if (discriminant == 0)  // One root
    {
        root1 = (-b) / (2 * a);
        root2 = root1;
        return 1;
    }
    // Two roots
    root1 = (-b - sqrt(discriminant)) / (2 * a);
    root2 = (-b + sqrt(discriminant)) / (2 * a);
    return 2;
}

int main()
{
    Eq2 eq1(1, -5, 6);   //discriminant=1,root1=2,root2=3
    Eq2 eq2(1, -6, 8);   //discriminant=4,root1=2,root2=4
    Eq2 eq3(1, 2, 3);
    Eq2 eq4(0, 0, 0);

    double root1, root2;
    Eq2 eqq[4] = { eq1,eq2,eq3,eq4 };
    for (int i = 0; i < 4; i++)
    {
        eqq[i].print();
    }

    int numRoots = eq1.Solve(root1, root2);

    switch (numRoots) {
    case 0:
        cout << "The the equation has no roots" << endl;
        break;
    case 1:
        cout << "The the equation has one root: " << root1 << endl;
        break;
    case 2:
        cout << "The the equation has two roots: " << root1 << ", " << root2 << endl;
        break;
    default:
        cout << "Error: This should be impossible" << endl;
        break;
    }
    system("pause");
    return 0;
}

答案 2 :(得分:1)

如注释中所建议:在这种情况下,“返回”是一个不明确的术语。您希望调用者能够获得第二级方程的根。

由于root1和root2是通过引用传递的,因此只需分配它们的值即可为调用者提供正确的值。您应该返回的是正确的。并且您应该检查判别式是否小于0并在这种情况下返回false。

如@Marichyasana所建议,可能所有int都应成为double

bool Solve(double& root1, double& root2)
{
    int discrimant = b*b - 4*a*c;
    if (discriminant < 0)
        return false;
    root1 = (-b - sqrt(discriminant))/(2*a);
    root2 = (-b + sqrt(discriminant))/(2*a);
    return true;
}

答案 3 :(得分:1)

我将在一个答案中总结评论中的所有建议:

  • 如果将非常量引用作为函数的参数传递,则可以更新它们的值,并且在最初调用该函数的代码中将保持更新
  • 您可能应该考虑使用double代替int,因为sqrt函数返回double
  • 如果计算失败,您还应该考虑添加一些检查,以便在这种情况下可以返回false,否则可以返回true

答案 4 :(得分:0)

签名很奇怪,返回根目录似乎更合适:

std::vector<double> SolveEq2(double a, double b, double c)
{
    if (a == 0) {
        throw std::runtime_error("Not equation of 2nd degree");
    }
    auto discriminant = b*b - 4*a*c;

    if (discriminant < 0) {
        return {}; // No roots;
    }
    else if (discriminant > 0)
    {
        auto sqrtDiscriminant = sqrt(discriminant);
        return {(-b - sqrtDiscriminant) / (2 * a),
                (-b + sqrtDiscriminant) / (2 * a)};
    } else { // == 0
        return {-b / (2 * a)};
    }
}

Demo