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

Поиск:

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


iOS Lead Developer
****


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

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



Ерунда какая-то получается.  Решаю биквадратное уравнение. Алгоритм продумал, он несложный, написал программу, но уперся в совершенно непонятную для меня ошибку. Компилятор Borland C++ 3.1, который я ненавижу, а что делать, в универе только его принимают.

Так. Запутался совсем с проверкой на ноль дробных чисел в Си. Привожу свое полное решение задачи, но оно не работает, сразу говорю, не проходят условия на проверку >, < или = 0. Чтоб эти дробные числа провалились уже. Помогите с этими условиями, остальное я сам доработаю.
Код

#include <stdio.h>
#include <math.h>
//--------------------------------------

int solveFullQuadEq(float A, float B, float C, float &x1, float &x2)
{
 //result - count of solutions

 float D = B*B - 4*A*C;

 if (D<0)
  return 0;

 if (D==0)
 {
  x1 = -B/2*A;
  return 1;
 }
 else
 {
  x1 = (-B+sqrt(D))/2*A;
  x2 = (-B-sqrt(D))/2*A;

  return 2;
 } 
}

//--------------------------------------
void main(void)
{
 const zeroCheck = 0.00001;

 float a,b,c;

 printf("A: "), scanf("%f", &a);
 printf("B: "), scanf("%f", &b);
 printf("C: "), scanf("%f", &c);

 if (fabs(a) < zeroCheck) //a==0
 {
  printf("Invalid input data!");
  return;
 }

 if (fabs(b) < zeroCheck) //b==0
 {
  if (c > 0)
  {
   printf("No solutions.");
   return;
  }
  else if (c < 0)
  {
   float r = sqrt(sqrt(b));
   printf("First solution: %.5f\nSecond solution: - %.5f", r, r);
   return;
  }
  else //c==0
  {
   printf("Solution: 0");
   return;
  }
 }
 else //b!=0
 {
  if (fabs(c) < zeroCheck)
  {
   printf("Solution: 0");
   return;
  }
  else
  {
   float r = sqrt(b);
   printf("First solution: 0\nSecond solution: %.5f\nThird solution: - %.5f", r, r);
   return;
  } 
 }
 else //full version
 { //for checking: x^4 + 4x^2 - 21 = 0, solutions are sqrt(3) and -sqrt(3)
  float x1, x2;

  if (solveFullQuadEq(a,b,c,x1,x2) == 1)
  {
   if (x1 >= 0)
   {
    float r = sqrt(x1);
    printf("Solution 1: %.5f\nSolution 2: - %.5f", r, r);
   }
   else printf("No solutions.");
  }
  else
  {
   float rx1, rx2;
   short flag1=0, flag2=0;

   if (x1 >= 0)
   {
    flag1 = 1;
    rx1 = sqrt(x1);
   }
   if (x2 >= 0)
   {
    flag2 = 1;
    rx2 = sqrt(x2);
   }

   if (flag1 && flag2)
    printf("Solution 1: %.5f\nSolution 2: - %.5f\nSolution 3: %.5f\nSolution 4: %.5f",rx1,rx1,rx2,rx2);
   else
   {
    if (flag1)
     printf("Solution 1: %.5f\nSolution 2: - %.5f", rx1, rx1);
    else if (flag2)
     printf("Solution 1: %.5f\nSolution 2: - %.5f", rx2, rx2);
   }
  }
 }
}

ЗЫ попутно еще вопрос... Логический тип в Си - bool ? А почему тогда Borland C++ его не понимает? И еще, если я написал какие-нить глупости в коде, прошу поправить...

Это сообщение отредактировал(а) mr.Anderson - 7.9.2008, 10:30


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

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


Explorer
****


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

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



Цитата(mr.Anderson @  6.9.2008,  21:23 Найти цитируемый пост)
Запускаю прогу, ввожу числа 1, 2, 3. И вываливаюсь по "Invalid input data!", хотя это бред!

канеш бред smile
Код

printf("Enter A: "), scanf("%d", &a);
 printf("Enter B: "), scanf("%d", &b);
 printf("Enter C: "), scanf("%d", &c);

Цитата(mr.Anderson @  6.9.2008,  21:23 Найти цитируемый пост)
Не получилось. Это условие теперь не выполняется при A != 0, но теперь непонятно, как прописать условие a > 0. Просто > 0? Или тоже константа нужна?

тут я не понял о чем ты smile


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


iOS Lead Developer
****


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

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



vinter, отредактировал. Ведь коэффициенты могут быть и дробными. С целыми-то все легко и просто. А вот с дробными как?


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

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


программист-самоучка
**


Профиль
Группа: Участник
Сообщений: 699
Регистрация: 12.1.2008
Где: ++Украина.Крым++

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



Цитата(mr.Anderson @  6.9.2008,  20:23 Найти цитируемый пост)
Логический тип в Си - bool ? А почему тогда Borland C++ его не понимает?

bool появился только в С++ (ну еще может быть в каких-то более поздних версиях Си)


--------------------

The code is the design ©

Sony VAIO VGN-FW480J

user posted image
PM MAIL ICQ   Вверх
Lazin
Дата 6.9.2008, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



зачем fabs вызывать для аргумента типа int?
PM MAIL Skype GTalk   Вверх
Hades
Дата 6.9.2008, 22:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Цитата(mr.Anderson @  6.9.2008,  20:23 Найти цитируемый пост)

Код

int a,b,c; 
printf("A: "), scanf("%f", &a); 
printf("B: "), scanf("%f", &b); 
printf("C: "), scanf("%f", &c);



mr.Anderson, если вводишь дробные числа, то и обьявляй их дробными.

P.S. Добро пожаловать в клуб программистов на BorlandC++ 3.1  smile 
PM MAIL   Вверх
vinter
Дата 6.9.2008, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


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

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



Цитата(mr.Anderson @  6.9.2008,  22:02 Найти цитируемый пост)
А вот с дробными как?

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


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


iOS Lead Developer
****


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

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



anatox91, бред какой-то. Куда ж без логики-то? И что вместо него использовать?
Lazin, угу, забыл объявление поправить. Но суть не в этом.
vinter, это я понял, а как проверить > < нуля? На равенство уже понятно.
Hades, спасибо, хотя Си и С++ ненавижу, а среду эту вообще глаза б не видели. А что делать.

Добавлено через 4 минуты и 36 секунд
Да, кстати, и что делает fabs()? Слова "возвращает абсолютное значение аргумента" мне мало о чем говорят...

Это сообщение отредактировал(а) mr.Anderson - 7.9.2008, 10:28


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

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


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

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



Цитата(mr.Anderson @  7.9.2008,  09:27 Найти цитируемый пост)
Да, кстати, и что делает fabs()? Слова "возвращает абсолютное значение аргумента" мне мало о чем говорят...

  Возвращает модуль числа с плавающей точкой smile .


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
vinter
Дата 7.9.2008, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


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

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



Цитата(mr.Anderson @  7.9.2008,  11:27 Найти цитируемый пост)
это я понял, а как проверить > < нуля? На равенство уже понятно.

a > e и a < -e smile

Цитата(mr.Anderson @  7.9.2008,  11:27 Найти цитируемый пост)
"возвращает абсолютное значение аргумента"

возаращет модуль вещественного числа.


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


iOS Lead Developer
****


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

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



Alexeis, vinter, спасибо, теперь въехал... smile "float abs", abs - модуль, а тут вещественный модуль... Понятно. smile

Попробую с эпсилонами этими сейчас.


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

user posted image
PM MAIL ICQ Skype   Вверх
Lazin
Дата 7.9.2008, 12:57 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Цитата(mr.Anderson @  7.9.2008,  10:27 Найти цитируемый пост)
Си и С++ ненавижу, а среду эту вообще глаза б не видели

вот оно тебе и платит тем-же smile 
PM MAIL Skype GTalk   Вверх
Ln78
Дата 7.9.2008, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(mr.Anderson @  6.9.2008,  21:23 Найти цитируемый пост)
x1 = (-B+sqrt(D))/2*A;

Вообще-то признания типа:
Цитата(mr.Anderson @  7.9.2008,  11:27 Найти цитируемый пост)
хотя Си и С++ ненавижу

не повышают желания помочь, но 2*А нужно брать в скобки, как, впрочем, и в паскале.
PM MAIL   Вверх
mr.Anderson
Дата 7.9.2008, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


iOS Lead Developer
****


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

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



Усе получилось. smile Проверил все описанные в программе варианты исхода, по-моему, это все возможные варианты. Все работают корректно.

Так что, я думаю, это полное решение биквадратного уравнения.
Код

#include <stdio.h>
#include <math.h>
//--------------------

int solveFullQuadEq(float A, float B, float C, float &x1, float &x2)
{
  //result - count of solutions

  const float eps = 0.00001;

  float D = B*B - 4*A*C;

  if (D < -eps) //D<0
    return 0;

  if (fabs(D) < eps) //D==0
  {
    x1 = -B/(2*A);

    return 1;
  }
  else //D>0, full quadratic equation
  {
    x1 = (-B+sqrt(D))/(2*A);
    x2 = (-B-sqrt(D))/(2*A);

    return 2;
  }
}

void main(void)
{
  const float eps = 0.00001;

  float a,b,c;

  printf("Enter A: "), scanf("%f", &a);
  printf("Enter B: "), scanf("%f", &b);
  printf("Enter C: "), scanf("%f", &c);

  if (fabs(a) < eps) //a==0
  {
    printf("Invalid input data!");
    return;
  }

  if (fabs(b) < eps) //b==0
  {
    if (c > eps) //c>0
    {
      printf("No solutions.");
      return;
    }
    else if (c < -eps) //c<0
    {
      float r = sqrt(sqrt(-c));
      printf("First solution: %.5f\nSecond solution: - %.5f", r, r);
      return;
    }
    else //c==0
    {
      printf("Solution: 0");
      return;
    }
  }
  else //b!=0
  {
    if (fabs(c) < eps) //c==0
    {
      if (b > eps) //b>0
      {
    printf("Solution: 0");
    return;
      }
      else //b<0
      {
    float r = sqrt(-b);
    printf("First solution: 0\nSecond solution: %.5f\nThird solution: - %.5f", r, r);
    return;
      }
    }
    else //full version
    { //for checking: x^4 + 4x^2 - 21 = 0, solutions are sqrt(3) and -sqrt(3)
      float x1, x2;

      if (solveFullQuadEq(a, b, c, x1, x2) == 1)
      {
    if (x1 >= eps)
    {
      float r = sqrt(x1);
      printf("Solution 1: %.5f\nSolution 2: - %.5f", r, r);
    }
    else printf("No solutions.");
      }
      else
      {
    float rx1,rx2;
    short flag1=0, flag2=0;

    if (x1 > eps)
    {
      flag1 = 1;
      rx1 = sqrt(x1);
    }
    if (x2 >= eps)
    {
      flag2 = 1;
      rx2 = sqrt(x2);
    }

    if (flag1 && flag2)
      printf( "Solution 1: %.5f\nSolution 2: - %.5f\nSolution 3: %.5f\nSolution 4: - %.5f",rx1,rx1,rx2,rx2);
    else
    {
      if (flag1)
        printf("Solution 1: %.5f\nSolution 2: - %.5f", rx1, rx1);
      else if (flag2)
        printf("Solution 1: %.5f\nSolution 2: - %.5f", rx2, rx2);
    }
      }
    }
  }
}


Добавлено @ 13:20
Lazin,  smile 

Ln78, угу.

Это сообщение отредактировал(а) mr.Anderson - 7.9.2008, 13:40


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

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


Explorer
****


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

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



Цитата(mr.Anderson @  7.9.2008,  14:19 Найти цитируемый пост)
if (fabs(a) < eps) //a<0 a==0




--------------------
Мой блог
PM MAIL WWW   Вверх
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   Вверх
Ln78
Дата 10.9.2008, 10:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(vinter @  10.9.2008,  10:32 Найти цитируемый пост)
float eps = 1.0e-612;
и  else  if ( fabs(D) < eps ), а то сравнение у тебя было не верно. 


vinter, 10 в минус шестой - это я у тебя взял. Если в минус 12-й, то непонятен смысл для других значений коэффициентов: для float, например 1+10^-8 = 1, какой смысл городить для этих значений ненужную проверку? С другой стороны, и для 10^-12 я могу взять коэффициенты уравнения, чтобы первый вариант давал верное решение, а второй - неправильное. 
А если ты считаешь, что сравнение у меня записано не так (хотя я так понял, что предлагаемый тобой вариант равносилен тому, что у меня названо вторым), напиши свой и приведи значения коэффициентов, когда он даёт лучшее решение, чем вариант, названный у меня первым.
PM MAIL   Вверх
vinter
Дата 10.9.2008, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


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

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



Цитата(Ln78 @  10.9.2008,  11:25 Найти цитируемый пост)
А если ты считаешь, что сравнение у меня записано не так (хотя я так понял, что предлагаемый тобой вариант равносилен тому, что у меня названо вторым),

нет не равносилен/ D < e не эквивалентно -e < D < e

Цитата(Ln78 @  10.9.2008,  11:25 Найти цитируемый пост)
какой смысл городить для этих значений ненужную проверку

как это ненужную? вот тебе пример из жизни, была у меня задача в ней были некие математические вычисления. И в результате должно было получится много нулей. Вместо них получались числа в -26 степен. Если сравнивать с нулем, то было бы не тру. Хотя реально это ноль.

Цитата(Ln78 @  10.9.2008,  11:25 Найти цитируемый пост)
С другой стороны, и для 10^-12 я могу взять коэффициенты уравнения, чтобы первый вариант давал верное решение, а второй - неправильное. 

Ln78 твои решения частные, я могу 1 поделитьт на max double и взять его эпсилоном, тогда ни одни твои коэффициенты не прокатят. Я не пойму, что ты мне пытаешься доказать.


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


Опытный
**


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

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



vinter, давай без ненужных философствований - приведи свой вариант, с эпсилонами, и покажи, чем он лучше. 
Цитата(vinter @  10.9.2008,  12:09 Найти цитируемый пост)
твои решения частные

Где ты это увидел? Для каких частных случаев вариант разработан, названный мною вариантом 1, и в чём вариант с эпсилонами более общий? Только приведи решение в виде кода и чисел, а не в виде общих рассуждений.

P.S. про
Цитата(vinter @  10.9.2008,  12:09 Найти цитируемый пост)
нет не равносилен/ D < e не эквивалентно -e < D < e

ты, возможно, не обратил внимание на else  в условии: else  if (D < eps).


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


Un salsero
Group Icon


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

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



Чего вы спорите?
vinter - прав, так как сравнивать вещественные числа в компьютерной программе без "зазора" нельзя!
Ln78 - прав, так как в правильном решении уравнения надо именно сравнивать на 0, а не на "зазор".

Один говорит, что слон большой, а другой - что слон серый smile





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


^аВаТаР^ сообщение>>
****


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

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



Цитата(Ln78 @  10.9.2008,  15:24 Найти цитируемый пост)

Где ты это увидел? Для каких частных случаев вариант разработан, названный мною вариантом 1, и в чём вариант с эпсилонами более общий? Только приведи решение в виде кода и чисел, а не в виде общих рассуждений.


Код

#include <stdio.h>
#include <math.h>

// mult*(x-delta)**2 = mult*(x**2-2*delta*x+delta*delta) 

int main()
{
     float A, B, C, x[2] = {0};
    float mult =5;
    float delta=3.333333;
      int N;
    A=mult;
    B=mult*(delta+delta);
    C=mult*delta*delta;
            
      float D = B*B - 4*A*C;
      char Buffer[120];
      float eps = 1.0e-6;
// 1-й вариант
    printf("%.13f\n", D);
      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;
      }
printf("%s\n", Buffer);
}

Цитата

-0.0001441107597
Нет действительных корней

Очевидно что вариант с эпсилонам тоже облажаеца. Так как подбирать коефициенты в лом, то делаем ход конём - меняем float на double.
Код

#include <stdio.h>
#include <math.h>

// mult*(x-delta)**2 = mult*(x**2-2*delta*x+delta*delta) 

int main()
{
     double A, B, C, x[2] = {0};
    double mult =5;
    double delta=3.333333;
      int N;
    A=mult;
    B=mult*(delta+delta);
    C=mult*delta*delta;
            
      double D = B*B - 4*A*C;
      char Buffer[120];
      double eps = 1.0e-6;
// 1-й вариант
    printf("%.13f\n", D);
      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;
      }
printf("%s\n", Buffer);
}

Цитата

0.0000000000002
Два действительных корня -3.33 и -3.33

Лажа дедекдет. Эпсилон здесь отработает нормально. Так как это очевидно то код писать не буду.

Это сообщение отредактировал(а) Mayk - 10.9.2008, 11:50


--------------------
 Здесь был кролик. Но его убили.
Человеки < кроликов, йа считаю.
PM MAIL WWW ICQ   Вверх
vinter
Дата 10.9.2008, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


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

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



Цитата(Ln78 @  10.9.2008,  12:24 Найти цитируемый пост)
приведи свой вариант, с эпсилонами, и покажи, чем он лучше. 

сходу пример не приведу, для этого нужны вычисления, а не константные числа.
Цитата(Ln78 @  10.9.2008,  12:24 Найти цитируемый пост)
ты, возможно, не обратил внимание на else  в условии: else  if (D < eps).

-1 < eps? но нельзя сказать что -1 равна нулю.


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


Опытный
**


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

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



Цитата(sergejzr @  10.9.2008,  12:44 Найти цитируемый пост)
Чего вы спорите?
vinter - прав, так как сравнивать вещественные числа в компьютерной программе без "зазора" нельзя!
Ln78 - прав, так как в правильном решении уравнения надо именно сравнивать на 0, а не на "зазор".

sergejzr, мы спорим о конкретном вопросе - имеет ли смысл писать эпсилон при решении квадратных уравнений. Не об абстрактном сравнении вещественных чисел вообще. Если говорить вообще, то сравнивать можно и так, и сяк, и наперекосяк, нужно только понимать, что это может за собой повлечь и как в каждой конкретной ситуации лучше делать. Для студента, чтобы решить его задачу, если он взялся учитывать машинную погрешность, тем самым как бы заявил, что не просто так бездумно запрограммировал формулы, а претендует на большее, нужно или писать намного более громоздко, учитывая и возможные переполнения при делении и прочее (при этом непонятно, почему используется float, а не long double), или не заморачиваться на эту тему вообще. Мне так кажется, что более простой вариант может быть засчитан как правильное решение.

Mayk, попытка хорошая. Однако у меня твоих результатов не было: в первом случае (float) оба варианта одинаково наврали, что корней нет. С типом double первый вариант выдал (если увеличить точность выдачи до 13 знаков после запятой), что имеются 2 действительных корня -3.333332952316 и -3.333333047684, второй честно сказал, что один действительный корень -3.333333 кратности 2. 
Учитывая даже такой "грех" первого варианта, если говорить о различных вариантах коэффициентов, в том числе и подобных тому, что я приводил, ты бы какой из вариантов посчитал лучшим? И, кстати, совершенно непонятно, что у тебя выдалось, ты ничего не напутал? Я смотрел на VS2005, процессор обычный интелловский, а ты где?

Отредактировано. - я не посмотрел, что ты выдавал только для первого варианта, дополнив выдачей дискриминанта. Этот вопрос снимаю. Вопрос про лучший вариант остаётся.

Цитата(vinter @  10.9.2008,  12:49 Найти цитируемый пост)
-1 < eps? но нельзя сказать что -1 равна нулю. 

vinter, посмотри внимательнее мой пример. Обрати внимание на самый первый if и учти, что  -1<-eps.


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


Explorer
****


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

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



Цитата(Ln78 @  10.9.2008,  13:44 Найти цитируемый пост)
мы спорим о конкретном вопросе - имеет ли смысл писать эпсилон при решении квадратных уравнений.


Ln78, мы спорим о сранении вещественных чисел в целом, а не в данном конкретном случае.


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


Опытный
**


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

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



Цитата(vinter @  10.9.2008,  13:49 Найти цитируемый пост)
Ln78, мы спорим о сранении вещественных чисел в целом, а не в данном конкретном случае. 

Ничего подобного smile . Перечитай мой первый пост:
Цитата(Ln78 @  9.9.2008,  21:12 Найти цитируемый пост)
Как раз эти форматы и определяют, что в данной ситуации прав NoliX, и число 10^-6, и даже 10^-26 - положительные

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

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

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

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

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


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

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


 




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


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

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