2010-11-03 2 views
-2

я следующий вызов:Алгоритм для нахождения нулевой точки

Реализовать функцию, которая ищет нулевой точки функции синусового в интервале между а и Ь. Интервал поиска [нижний предел, верхний предел] должен быть уменьшен до половины, а нижний предел и верхний предел меньше 0,0001 друг от друга.

  1. Найти условия, в которых разрешенный интервал поиска должен быть продолжен. Поэтому, сократив интервал на два интервала, мы должны выбрать один, чтобы продолжить наш поиск.

  2. Мы предполагаем, что в интервале между a и b имеется только одна нулевая точка.

alt text

Я борюсь с точкой 1. У меня уже были некоторые вопросы по этой теме, которые помогли мне много, но теперь мне нужно реализовать в Java, но это еще не работает.

Вот мой код до сих пор:

private static double nullstelle(double a, double b){ 
     double middle = (a + b)/2; 
     double result = middle; 

     if(Math.abs(a-b) > 0.0001){ 
      double sin = Math.sin(middle); 
      if(sin > 0){ 
       result = nullstelle(a, middle); 
      }else{ 
       result = nullstelle(middle, b); 
      } 
     } 
     return result; 
    } 

Я пытался реализовать с помощью рекурсии, но, может быть, другой способ будет лучше, я не знаю. Любые идеи?

+1

Разве это не тот же самый вопрос, который вы размещены здесь: http://stackoverflow.com/questions/4086385/find-zero-points-with -recursion – Grodriguez

+1

О, а также здесь: http://stackoverflow.com/questions/4085115/find-null-points-of-sinus-function – Grodriguez

+1

Если x1 и x2 на графике являются значениями, которые вы используете для 'a 'и' b', ваши тестовые данные нарушают предположение в 2). – Simon

ответ

2

Если есть только одна нулевая точка между а и Ь, что означает знак (грех (а))! = Знак (син (б)).При замене а или б с середины точки, вы должны убедиться, что это по-прежнему так, делая что-то вроде этого:

if (sign(sin(a)) == sign(sin(middle))) 
    result = nullstelle(middle, b); 
else 
    result = nullstelle(a, middle); 

со знаком (х) определяется как

int sign(double x) { return x >= 0 ? 1 : -1; } 
+0

это делает меня сумасшедшим: D для [ 5,8] Я получаю 5,7499 ... это должно быть 6, ... –

+0

сейчас он работает, спасибо! –

1

Вы почти правильно поняли. Вы выбираете интервал на основе изменения знака - если знак меняется между левой и правой границы интервала, вы выбираете этот интервал:

private static double nullstelle(double a, double b){ 
     double middle = (a + b)/2; 
     double result = middle; 

     if(Math.abs(a-b) > 0.0001){ 
      double sin = Math.sin(middle); 
      if(sin == 0) { // Rare case but might happen 
       result = middle; 
      } else if (Math.signum(sin) != Math.signum(b)) { // The sign changes between middle and b 
       result = nullstelle(middle, b); 
      } else if (Math.signum(sin) != Math.signum(a)) { // The sign changes between a and middle 
       result = nullstelle(a, middle); 
      } else { 
       // Throw an exception here, the sin function does not cross x axis in the given interval 
      } 
     } 
     return result; 
    } 

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

+0

он возвращает 6,5 для [5,8], что-то не так –

2

Поскольку существует не более одного перехода через ноль в нашем рассматриваемом интервале, есть три возможности:

  1. Нулевая точка находится в левой половине
  2. Нулевая точка находится в правой половине
  3. The bisection - это нулевая точка.

Если точка бисекции - это нулевая точка, все готово.

В противном случае сегмент, содержащий пересечение нуля, должен иметь разные знаки на своих конечных точках.

Recurse на участке, который имеет разные знаки на своих конечных точек

1

дал x в [a, b] изобилующем интервале (a < = x < = b) можно сказать, что приложение f: [a, b] -> R имеет корень на [a, b], т. е. в ограниченный интервал [a, b], который удовлетворяет f (x) = o тогда и только тогда, когда f (a) * f (b) < 0.

Простыми словами есть корень на интервале - это знак изменения функции на этом интервале.

Чтобы найти эту точку, мы будем использовать двоичное разбиение интервала.

Я бы изменить этот код, как это следующим образом:

private static double nullstelle(double a, double b){ 
     double middle = (a + b)/2; 

     if(Math.abs(a-b) < 0.0001){ 
      return middle; 
     } 
     if(Math.sin(a)*Math.sin(middle)<0) { 
      return nullstelle(a, middle); 
     } 
     if(Math.sin(middle)*Math.sin(b)<0) { 
      return nullstelle(middle, b); 
     } 
    } 
Смежные вопросы