-3

I'm having issues with the code below:

#include<iostream>
#include<fstream>
#include<cmath>

using namespace std;

int main()
{
    ifstream fin("input.txt");
    ofstream fout("output.txt");

    float discriminant, A, B, C, root1, root2;

    fin >> A >> B >> C;

    while (A != -99)
    {
        discriminant = (pow(B, 2.0) - 4 * A*C);

        if (A == 0)
        {
            fout << A << "\t" << B << "\t" << C << "\t" << root1 << "\t" << root2 << endl;
        }

        else if (discriminant > 0)
        {
            root1 = (-B - sqrt(discriminant)) / (2.0*A);
            root2 = (-B + sqrt(discriminant)) / (2.0*A);
            fout << A << "\t" << B << "\t" << C << "\t" << root1 << "\t" << root2 << endl;
        }

        else if (discriminant == 0)
        {
            fout << A << "\t" << B << "\t" << C << "\t" << root1 << "\t" << root2 << endl;
        }

        else
        {
            fout << A << "\t" << B << "\t" << C << "\t" << root1 << "\t" << root2 << endl;
        }

        fin >> A >> B >> C;
    }

    fout.close();

    ifstream fin2("output.txt");

    fin2 >> A >> B >> C >> root1 >> root2;

    while (!fin2.eof())
    {
        cout << A << "\t" << B << "\t" << C << "\t" << root1 << "\t" << root2 << endl;

        fin2 >> A >> B >> C >> root1 >> root2;
    }

    cout << endl;
    cout << "Coded by Paye W. Kialain" << "\t"<< endl;
    system("pause");
    return 0;
}

In the project description, I was told to create an input file containing a, b, and c, which I did. The format of the output is also correct. It is a table displaying the a, b and c values along with the 2 calculated roots. However, the calculations of the roots seem to be off. Are my if statements the issue?

Gnqz
  • 3,292
  • 3
  • 25
  • 35
  • 2
    Maybe you can tell us what inputs give what wrong outputs. – Michael Burr Mar 02 '16 at 19:26
  • The inputs are: 6 -10 -4 2 6 9 2 4 8 0 2 4 2 4 2 But the output seems to be: 6 -10 -4 -0.333333 2 2 6 9 -0.333333 2 2 4 8 -0.333333 2 0 2 4 -0.333333 2 2 4 2 -0.333333 2 Coded by Paye W. Kialain Press any key to continue . . . – M. Liberian Mar 02 '16 at 19:42
  • Details of some of whats going wrong here: [Why Are Floating Point Numbers Inaccurate?](http://stackoverflow.com/questions/21895756/why-are-floating-point-numbers-inaccurate) – user4581301 Mar 02 '16 at 19:46
  • 1
    @M.Liberian edit the question to include the input and output. Easier to read and find. Also worth adding what you expected the output to be. – user4581301 Mar 02 '16 at 19:48
  • Recommend replacing `while (!fin2.eof())` with `while (!fin2.eof(fin2 >> A >> B >> C >> root1 >> root2))` and getting rid of the two `fin2 >> A >> B >> C >> root1 >> root2;`s. Bit easier to read and catches poorly formatted input as well as end of file. Current could trip over bad input and go into infinite loop because the bad read is never handled and cleared. – user4581301 Mar 02 '16 at 19:54
  • Why `while (A != -99)`? – user4581301 Mar 02 '16 at 20:02
  • `root1` and `root2` can be used before they are initialized. – user4581301 Mar 02 '16 at 20:09

1 Answers1

1

The statements discriminant == 0 and A == 0 are dangerous comparisons because discriminant and A are floats. Floating-point calculations are often accompanied with floating-point errors (Think errors you get in mathematical approximations).

Consider this simple example of floating-point errors:

#include <iostream>
#include <string>

int main()
{
  float a = 3.0;
  float b = 10.0;
  std::cout.precision(20);
  std::cout << a/b << std::endl;
}

3.0/10.0, that's elementary math! You'd expect the result to be 0.3. However, as it turns out, the result is 0.30000001192092895508. If a and b were doubles, the result would be 0.2999999999999999889. This is because the way floating-point numbers are represented in binary does not allow for an accurate representation of 0.3. Now imagine what would have happened if I had code like if(a/b == 0.3). The condition will never be satisfied.

A solution to this problem is to introduce an epsilon value. This epsilon value basically serves as a value for error tolerance.

float a = 3.0;
float b = 10.0;

const float epsilon = 0.000001;

if(fabs(a/b - 0.3) < epsilon) {
  std::cout << "a/b is equal to 0.3!" << std::endl;
}
Nard
  • 1,006
  • 7
  • 8
  • Thanks for the help! However, I'm unsure how to incorporate the epsilon constant without complicating everything; and will that stop the code from giving the same value for every root1 and root2 value? – M. Liberian Mar 02 '16 at 19:52
  • Think of the `epsilon` method as the "safe" version of `some_float == 0`. I don't see how it would complicate anything. You'll have to try it out yourself. You can't get anywhere with programming if you can't be bothered with or afraid to experiment and iterate. – Nard Mar 02 '16 at 20:10