-2

Проверка ЯндексКонтест выдает ошибку при 3 проверке программы, самостоятельно ошибку найти не могу.Вот условие:

Формат ввода Входной файл содержит три целых числа a, b и c, не превосходящих по модулю 10^9, — коэффициенты уравнения ax2 + bx + c = 0.

Формат вывода В первой строке вывода требуется указать число различных решений этого уравнения. Далее выведите корни уравнения с точностью до 6 знаков после запятой, по одному в строке. Корни должны следовать в порядке возрастания.

Если корней бесконечно много, выведите ровно одно число, -1.

Вот код:

using namespace std; 

int main () { 
double a,b,c,d,x1,x2;

 cin>>a>>b>>c; 

    if((c==0 && b==0 && a==0)) cout<<-1; 
    else if((b==0 && c==0)||(a==0 && c==0)) cout<<1<<"\n"<<0;
    else { 
  d=b*b-4*a*c; 
  b=-b; 
 a=a*2; 

if(d==0) cout<<1<<"\n"<<b/a; 

else if(d<0) cout<<0; 

 else if(d>0){ 
 cout<<2<<"\n"; 
 x1=(b+sqrt(d))/a; 
x2=(b-sqrt(d))/a; 
 if(x1<x2) {cout<<setprecision(7)<<x1<<"\n"<<setprecision(7)<<x2;} 
else {cout<<setprecision(7)<<x2<<"\n"<<setprecision(7)<<x1;} } 
return 0; 
 }}
  • 1
    Я бы до последнего работал с long long int (вытягивало бы дискриминант точно), а не double... если и это не прошло бы - то добавлял бы уточнения - типа, для b^2 >> 4ac - брал бы формулу поточнее. – Harry Jul 25 '18 at 18:48
  • Не помешало бы добавить << std::fixed. – HolyBlackCat Jul 25 '18 at 18:52
  • Я не особо знаю язык, но как минимум вы не задаёте точность вывода если корень один – Alexey Ten Jul 25 '18 at 20:56
  • И сравнение double с нулём тоже вызывает подозрение – Alexey Ten Jul 25 '18 at 20:58
  • А вариант a = 0, b = 0, c != 0 вам не надо отлавливать как "корней нет"? – AnT stands with Russia Jul 25 '18 at 21:14

2 Answers2

4

Я не знаю, содержат ли тестовые данные такие входы, на которых будет проявляться явление "catastrophic cancellation", приводящее к катастрофической потере точности в арифметике с плавающей точкой, но тем не менее:

В ситуации, когда корней два, более правильной техникой нахождения этих корней в арифметике с плавающей точностью будет

double d = b * b - 4 * a * c; 
double q = b >= 0 ? (-b - sqrt(d)) / 2  : (-b + sqrt(d)) / 2; 
double x1 = q / a;
double x2 = c / q;

Такой вариант намного более устойчив к catastrophic cancellation (https://ru.stackoverflow.com/a/493642/182825)

Например, на входных данных

a = 1, b = -1000000000, c = 1

(что находится в пределах диапазона задания) мой вариант дает решение

x1 = 1000000000, x2 = 1.0000000000000000623e-09

а ваш вариант дает

x1 = 1000000000, x2 = 0

Как видите, погрешность на x2 в вашем случае существенно выше, хотя и в пределах требуемой точности.


Также у вас, вроде бы, не рассмотрен случай a = 0, b = 0, c != 0.

0
  1. 0*x2 + 0*x + 7 = 0
  2. Дробные числа не стоит сравнивать на равенство.
    Безопасно ли сравнение == для типа double?
Qwertiy
  • 123,725