Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Решение биквадратного уравнения, не могу найти ошибку 
:(
    Опции темы
mr.Anderson
Дата 7.9.2008, 13:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


Профиль
Группа: Участник Клуба
Сообщений: 3374
Регистрация: 20.12.2004
Где: далеко

Репутация: 1
Всего: 128



vinter, ага, очепяток


--------------------
user posted image

user posted image
PM MAIL ICQ Skype   Вверх
NoliX
Дата 8.9.2008, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 5.7.2005

Репутация: 1
Всего: 1



Цитата

дробные так не проверяются. Дробные надо сверять по какой-то бесконечно малой епсилон. Допустим тебе надо сравнить две переменные типа float\double => |a - b| < e, где e допустим 0.000001


По-моему в данной задаче это не уместно, тут идет сравнение только с нулем, для определения положительности или отрицательности никакие малые величины не нужны, если же требуется установить, что переменная равна нулю, то в данной задаче необходимо полное совпадение перемнной с нулем, тоесть '==', если мы будем смотреть, попадает ли одно число в окрестность заданного радиуса другого, то потеряем точность и вместо 2-х различных по модулю корней получим один

мое видение задачи:

Код

    float cA,cB,cC;
    printf("A: "), scanf("%f", &cA);
    printf("B: "), scanf("%f", &cB);
    printf("C: "), scanf("%f", &cC);

    float disc=cB*cB-4*cA*cC;
    
    if (disc>=0){
        if (disc==0){
            int res=-cB/(2*cA);
            if (res>=0){
                if (res>0){
                    printf("x1==%f\n", +sqrt(res));
                    printf("x2==%f\n", -sqrt(res));
                }
                if (res==0)
                    printf("x==0");
            }
            else
                printf("No real solutions.");

        }
        if (disc>0){
            float res1=(-cB+sqrt(disc))/(2*cA);
            if (res1>0){                    
                printf("x11==%f\n", +sqrt(res1));
                printf("x12==%f\n", -sqrt(res1));
            }
            float res2=(-cB-sqrt(disc))/(2*cA);
            if (res2>0){                    
                printf("x21==%f\n", +sqrt(res2));
                printf("x22==%f\n", -sqrt(res2));
            }
        }

    }
    else
        printf("No real solutions.");



код не тестил (у меня студия), могут быть косяки, но логика должна быть понятна

Это сообщение отредактировал(а) NoliX - 8.9.2008, 17:23
--------------------
Опыт - это учитель, который очень дорого берет за свои уроки
PM MAIL   Вверх
vinter
Дата 8.9.2008, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(NoliX @  8.9.2008,  18:08 Найти цитируемый пост)
то в данной задаче необходимо полное совпадение перемнной с нулем, тоесть '=='

так числа с плавающей точкой сравнивать нельзя
0.000001 это что за число? как его интерпритировать? 0? > нуля?


--------------------
Мой блог
PM MAIL WWW   Вверх
NoliX
Дата 8.9.2008, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 5.7.2005

Репутация: 1
Всего: 1



это число положительно, имеет знак + => оно больше нуля
тем, что Вы оцениваете модуль разности какм-то эпсилон Вы только увеличиваете погрешность сравнения со стандартной Борландовской до Вашей 0.000001

Хотя может я чего-то не догоняю, конечно, но если у двух чивел различие в 30-м знаке после запятой, то в тип float он не влезет и такие числа будут равны, так как n знаков просто обрежутся, если сравнивать через оценку, то по Вашему числа 0.0000005 и 0.0000006 равны

Это сообщение отредактировал(а) NoliX - 8.9.2008, 20:37
--------------------
Опыт - это учитель, который очень дорого берет за свои уроки
PM MAIL   Вверх
Lazin
Дата 8.9.2008, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



Цитата(NoliX @  8.9.2008,  20:34 Найти цитируемый пост)
Хотя может я чего-то не догоняю

почитай про форматы чисел с плавающей запятой, абсолютное значение числа, которое можно хранить в переменной типа float ограничен как сверху, так и снизу
PM MAIL Skype GTalk   Вверх
NoliX
Дата 8.9.2008, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 5.7.2005

Репутация: 1
Всего: 1



Цитата

почитай про форматы чисел с плавающей запятой, абсолютное значение числа, которое можно хранить в переменной типа float ограничен как сверху, так и снизу


Да я знаю, вот и вводя эпсилон мы искусственно ухудшаем ситуацию, я не знаю как еще объяснить? единственное чего я не знаю, это какое самое маленькое число может храниться во float

Кстати я не против такого метода, я, просто, говорю, что тут не нужно мудрить, если число не равно нулю (а это ведь дискриминант) и с положительным знаком, то оно нам подходит
Сравнение двух, черти каких чисел, очевидно, нужно производить оценкой модуля разности

Это сообщение отредактировал(а) NoliX - 8.9.2008, 21:00
--------------------
Опыт - это учитель, который очень дорого берет за свои уроки
PM MAIL   Вверх
vinter
Дата 9.9.2008, 00:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(NoliX @  8.9.2008,  21:34 Найти цитируемый пост)
это число положительно, имеет знак + => оно больше нуля

с чего такой вывод, так может храниться и ноль ;)
P.S давай на ты, не люблю когда Выкают 


--------------------
Мой блог
PM MAIL WWW   Вверх
NoliX
Дата 9.9.2008, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 103
Регистрация: 5.7.2005

Репутация: 1
Всего: 1



Цитата

P.S давай на ты, не люблю когда Выкают 

Это профессиональная привычка, у нас тут так принято)

В общем ладно, скорее всего оно так и есть
Про сравнение двух чисел я знаю, а вот с нулем, мне казалось, что все проще
--------------------
Опыт - это учитель, который очень дорого берет за свои уроки
PM MAIL   Вверх
vinter
Дата 9.9.2008, 16:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(NoliX @  9.9.2008,  17:36 Найти цитируемый пост)
Это профессиональная привычка, у нас тут так принято)

мм, у нас тут так не принято smile


--------------------
Мой блог
PM MAIL WWW   Вверх
sergejzr
Дата 9.9.2008, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Un salsero
Group Icon


Профиль
Группа: Админ
Сообщений: 13285
Регистрация: 10.2.2004
Где: Германия г .Ганновер

Репутация: нет
Всего: 360



Цитата(mr.Anderson @  7.9.2008,  12:19 Найти цитируемый пост)
Усе получилось. smile Проверил все описанные в программе варианты исхода, по-моему, это все возможные варианты. Все работают корректно.


Цитата(NoliX @  8.9.2008,  16:08 Найти цитируемый пост)
По-моему в данной задаче это не уместно, тут идет сравнение только с нулем, для определения положительности или отрицательности никакие малые величины не нужны, если же требуется установить, что переменная равна нулю, то в данной задаче необходимо полное совпадение перемнной с нулем, тоесть '==', если мы будем смотреть, попадает ли одно число в окрестность заданного радиуса другого, то потеряем точность и вместо 2-х различных по модулю корней получим один


Можно определить диапазон чисел, в котором будет работать алгоритм и использовать только целые. (из 0.001 делать 0.001*1000=1)




--------------------
PM WWW IM ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Ln78
Дата 9.9.2008, 20:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: нет
Всего: 15



Цитата(vinter @  8.9.2008,  20:08 Найти цитируемый пост)
так числа с плавающей точкой сравнивать нельзя
0.000001 это что за число? как его интерпритировать? 0? > нуля? 

Цитата(Lazin @  8.9.2008,  21:43 Найти цитируемый пост)
почитай про форматы чисел с плавающей запятой, абсолютное значение числа, которое можно хранить в переменной типа float ограничен как сверху, так и снизу 

Как раз эти форматы и определяют, что в данной ситуации прав NoliX, и число 10^-6, и даже 10^-26 - положительные. И уж точно ничего не улучшится от введения дополнительной искуственной погрешности в данном случае. И сравнение с нулём именно такое (==0) в данном случае наиболее разумно. Вещественное число такое же устойчивое, как и целое в том смысле, что его разряды от ветра и температуры процессора не зависят. 
И даже в тех случаях, когда нужно учитывать погрешность при сравнении, важно не забывать, что это числа с плавающей, а не фиксированной запятой. Поэтому просто 10^-6 безотносительно остальных параметров (коэффициенты уравнения порядка 1; 10^10; 10^-10), как правило, не является лучшим решением.
PM MAIL   Вверх
vinter
Дата 9.9.2008, 20:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(Ln78 @  9.9.2008,  21:12 Найти цитируемый пост)
И сравнение с нулём именно такое (==0) в данном случае наиболее разумно.

иди учи матчасть, я еще раз повторяю "Так вещественные числа не сравнивают"


--------------------
Мой блог
PM MAIL WWW   Вверх
Lazin
Дата 9.9.2008, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 27
Всего: 154



если число ввели с клавиатуры, то оно вполне может быть точно равно 0, если же число получено в вычислениях, то там чаще всего будет 10^(-много), так что вот так... smile 
PM MAIL Skype GTalk   Вверх
Ln78
Дата 10.9.2008, 07:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 274
Регистрация: 25.11.2006

Репутация: нет
Всего: 15



Цитата(vinter @  9.9.2008,  21:26 Найти цитируемый пост)
Цитата(Ln78 @  9.9.2008,  21:12 )
И сравнение с нулём именно такое (==0) в данном случае наиболее разумно.

иди учи матчасть, я еще раз повторяю "Так вещественные числа не сравнивают" 

vinter, заявление категоричное по сути и хамоватое по форме. Учитывая формулировки вида
Цитата(vinter @  7.9.2008,  00:04 Найти цитируемый пост)
Дробные надо сверять по какой-то бесконечно малой епсилон

матчасть хорошо бы подтянуть тебе, чтобы отличать бесконечно малый эпсилон от машинного эпсилона.  
Чтобы обсуждение было предметным, посмотри на пример:
Код

      float A, B, C, x[2] = {0};
      int N;
      A = 1.0e-5; B = -3.0e-5; C = 2.0e-5;
      float D = B*B - 4*A*C;
      char Buffer[120];
      float eps = 1.0e-6;

// 1-й вариант
      if (D<0)
      {
         N = 0;
         sprintf(Buffer, "Нет действительных корней" );
      }
      else  if (D==0)
      {
         x[0] = -B/(2*A);
         sprintf(Buffer, "Один действительный корень %.3g кратности 2", x[0] );
         N = 1;
      }
      else
      {
         x[0] = (-B+sqrt(D))/(2*A);
         x[1] = (-B-sqrt(D))/(2*A);
         sprintf(Buffer, "Два действительных корня %.3g и %.3g", x[0], x[1] );
         N = 2;
      }

 // 2-й вариант
      if (D < -eps)
      {
         N = 0;
         sprintf(Buffer, "Нет действительных корней" );
      }
      else  if (D < eps)
      {
         x[0] = -B/(2*A);
         sprintf(Buffer, "Один действительный корень %.3g кратности 2", x[0] );
         N = 1;
      }
      else
      {
         x[0] = (-B+sqrt(D))/(2*A);
         x[1] = (-B-sqrt(D))/(2*A);
         sprintf(Buffer, "Два действительных корня %.3g и %.3g", x[0], x[1] );
         N = 2;
      }

При указанных мною коэффициентах очевидно второй вариант - ошибочный. Приведи такие значения коэффициентов квадратного уравнения, когда второй вариант лучше.

Это сообщение отредактировал(а) Ln78 - 10.9.2008, 07:03
PM MAIL   Вверх
vinter
Дата 10.9.2008, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

Репутация: 8
Всего: 56



Цитата(Ln78 @  10.9.2008,  08:01 Найти цитируемый пост)
хамоватое по форме

извини, не хотел обидеть smile

Ln78, хитрый какой smile эпсилон надо подбирать в сооответсвии с коэффициентами, если уж ты их знаешь ;)
 float eps = 1.0e-612;
и  else  if ( fabs(D) < eps ), а то сравнение у тебя было не верно.


--------------------
Мой блог
PM MAIL WWW   Вверх
Страницы: (3) Все 1 [2] 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0621 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.