C ++: Как вы определяете, является ли решение тривиальным или не существует для квадратичной функции?

Я работаю над программой, которая должна вычислять корни квадратичной функции и выводить ее корни. Тем не менее, вывод не то, что он должен быть для всех случаев. Когда предполагается, что он не имеет решений или тривиален, он выводит как -nan(ind), Когда у него должно быть одно решение, оно выводит x1 = -nan(ind) а также x2 = -inf, Я не слишком уверен, почему это происходит, и я мог бы действительно использовать некоторую помощь. Вот мой код:

#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

int main() {

// Initialize and define the variables:
// a = the variable that stores the value for 'a' in the quadratic
// b = the variable that stores the value for 'b' in the quadratic
// c = the variable that stores the value for 'c' in the quadratic
// d = the variable that stores the determinant of the quadratic function to find the nature of the roots (b^2-4ac)
// root1 = the variable that stores the first possible root of a quadratic function
// root2 = the variable that stores the second possible root of a quadratic function
// realNum = the variable that stores the real portion of the complex roots
// imaginaryNum = the variable that stores the imaginary portion of the complex roots
double a, b, c, d, root1, root2, realNum, imaginaryNum;

// Ask the user to input a value for variable 'a' of the quadratic
// NOTE: 'setprecision' specifies the minimum precision, 'fixed' states a fixed number of decimals will
// appear after the entered digit
cout << "Please input a: " << setprecision(4) << fixed;
cin >> a;                                   /// Store the value in variable 'a'

// Ask the user to input a value for variable 'b' of the quadratic
// NOTE: 'setprecision' specifies the minimum precision, 'fixed' states a fixed number of decimals will
// appear after the entered digit
cout << "Please input b: " << setprecision(4) << fixed;;
cin >> b;                                   /// Store the value in variable 'b'

// Ask the user to input a value for variable 'c' of the quadratic
// NOTE: 'setprecision' specifies the minimum precision, 'fixed' states a fixed number of decimals will
// appear after the entered digit
cout << "Please input c: " << setprecision(4) << fixed;;
cin >> c;                                   /// Store the value in variable 'c'

// Calculate the determinant of the quadratic (b^2 - 2ac)
d = ((pow(b, 2.0)) - (4 * a * c));// Check to see if the determinant is greater than 0
if (d >= 0) {

// Calculate each of the two possible roots for the quadratic
root1 = (-b + sqrt(d)) / (2 * a);
root2 = (-b - sqrt(d)) / (2 * a);

// Display to the user that a solution does exist for the following quadratic
cout << "Your equation has real roots: " << root1 << " and " << root2 << "." << endl;

}// Check to see if the determinant is greater than 0
else if (d < 0) {

// Calculate the real portion of the complex roots for the quadratic
realNum = (-b) / (2 * a);

// Calculate the imaginary portion of the complex roots for the quadratic
imaginaryNum = (sqrt(-d)) / (2 * a);

// Combine the two portions of the complex roots and display the calculated complex roots to the user
cout << "Your equation has complex roots: " << realNum << " + " << imaginaryNum << "i and "<< realNum << " - " << imaginaryNum << "i." << endl;

}

// Indicate that the program ended successfully
return 0;

} // End of function main

0

Решение

Во-первых, если а крошечный, мы можем сказать, что квадратный член исчезает. Таким образом, она становится прямой линией с одним корнем (если она не параллельна оси x).

Тогда, если определитель отрицателен, уравнение не пересекает ось х. Таким образом, нет никаких корней или, если хотите, корни воображаемые.

Чтобы улучшить числовую стабильность, используйте эту функцию. Это написано, чтобы избежать почти 0/0 термина, который может возникнуть с помощью формулы старшей школы.

int quadratic_roots(double a, double b, double c, double *out)
{
double rootb2minus4ac;
double b2minus4ac;

if(fabs(a) < FLT_EPSILON * 0.01)
{
if(fabs(b) > FLT_EPSILON * 0.01)
{
out[0] = c/-b;
return 1;
}
return 0;
}

b2minus4ac = b*b - 4*a*c;
if(b2minus4ac > 0)
{
rootb2minus4ac = sqrt(b*b - 4*a*c);
if(b >= 0)
{
out[0] = (-b -rootb2minus4ac)/(2*a);
out[1] = (2*c)/ (-b -rootb2minus4ac);
}
else
{
out[0] = (2*c)/(-b + rootb2minus4ac);
out[1] = (-b + rootb2minus4ac)/(2*a);
}
if(a < 0)
{
double temp = out[0];
out[0] = out[1];
out[1] = temp;
}
return 2;
}
else if(b2minus4ac == 0.0)
{
out[0] = (2*c)/-b;
return 1;
}
return 0;
}
0

Другие решения

Проблема в том, что вы делите на 0 здесь:

 imaginaryNum = (sqrt(-d)) / (2 * a);

Поведение поплавков определяется IEEE-754 Стандарт. В нем говорится, что если вы разделите число на 0, число будет представлено как бесконечность. Кроме того, деление на ноль неопределенное поведение в C ++.

Вот почему вы хотите проверить пользовательский ввод. Вы можете не вводить недействительные числа, но пользователь может очень хорошо. Этот код будет временным решением. Обратите внимание, что это только временное решение вашей проблемы, потому что такие строки, как «12a», все равно будут приниматься:

#include <iostream>
#include <exception>

int main() {
double input;
bool is_valid = false;
while (is_valid != true) {
try {
cin >> input; //
if (!cin) {
cin.clear(); // reset failbit
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
throw std::bad_exception();
}
else {
is_valid = true;
}
}
catch (...) {
std::cout << "Input a number!\n";
}
}
// ... Do this for all your inputs and proceed.
}
0

Вот проблемные части вашего кода:

// Calculate each of the two possible roots for the quadratic
root1 = (-b + sqrt(d)) / (2 * a);
root2 = (-b - sqrt(d)) / (2 * a);
//....
// Calculate the real portion of the complex roots for the quadratic
realNum = (-b) / (2 * a);

// Calculate the imaginary portion of the complex roots for the quadratic
imaginaryNum = (sqrt(-d)) / (2 * a);

Как ясно видно, переменная в знаменателе. Переменная могу иметь любой значение, в том числе ноль. Деление на ноль, может привести к Неопределенное поведение в C ++. Также как указано Scy:

Поведение поплавков определяется Стандарт IEEE-754. Говорится
что если вы разделите число на 0, то число будет представлено как
бесконечность.

Мое предложение состоит в том, чтобы проверить, равен нулю или нет. Если равен нулю, тогда выкинь ошибку.

cout << "Please input a: " << setprecision(4) << fixed;
cin >> a;
if (a == 0){
std::cerr << "The variable a should not be equal with 0";
return 1;
}

Я настоятельно рекомендую вам создать функцию для вычисления корней любого заданного полинома. Это может сделать ваш код более читабельным и более эффективным. Кроме того, функция main () на самом деле не так уж многократна, поэтому ее следует сохранять короткой.

0
По вопросам рекламы [email protected]