2015-08-18 3 views
0

Я работаю над алгоритмом, который может вычислять длину кривой с использованием элементарных сегментов. Поэтому, если у меня есть вектор координат x и y кривой, мне нужно вычислить число этих элементарных сегментов. Я придумал для этого свой собственный рекурсивный алгоритм. Существует код:Дефект сегментации (core dumped) - векторы

#include <iostream> 
#include <vector> 
#include <cmath> 

using namespace std; 
//*********************************************** 
inline double Pitagoras(double xp, double yp, double xf, double yf) 
{ 
    return sqrt((xp - xf)*(xp - xf) + (yp - yf)*(yp - yf)); 
} 
//*************************************************** 
inline double calculateX(double xp, double yp, double a, double b, const double eps) 
{ 
    double delta; 
    double x1, x2; 

    delta = (-2.0 * xp + 2.0 *a*b - 2.0 *a*yp)*(-2.0 * xp + 2.0 *a*b - 2.0 *a*yp) 
     - 4.0* (1.0 + a*a)*(xp*xp + yp*yp + b*b - 2.0*b*yp - eps*eps); 

    x1 = (-(-2.0 * xp + 2.0 *a*b - 2.0 *a*yp) - sqrt(delta))/(2.0 * (1.0 + a*a)); 
    x2 = (-(-2.0 * xp + 2.0 *a*b - 2.0 *a*yp) + sqrt(delta))/(2.0 * (1.0 + a*a)); 

    if(x1 >= xp) 
    return x1; 
    else 
     return x2; 
} 
//*************************************************** 
inline double calculateY(double x, double a, double b) 
{ 
    return a*x + b; 
} 
//*********************************************** 
unsigned long algorithmKolmogorow(double xp, double yp, double xf, 
double yf, const double eps, vector<double> &vectorX, vector<double> &vectorY); 
//*********************************************** 
int main() 
{ 
    vector<double> vctrY; //vector of value of function 
    vector<double> vctrX; //vector of x 
    double xP,yP,xF,yF; //coordinates of two points on the curve 
    const double Eps = 0.0001; //length of elementary line 

     for(double x=1.0; x<=5 ;x +=0.001) 
     { 
      vctrX.push_back(x); 
      vctrY.push_back(x*x); //f(x) = x^2 
     } 

    xP = vctrX[0]; 
    yP = vctrY[0]; 
    xF = vctrX[1]; 
    yF = vctrY[1]; //set beginning value 

    cout<<algorithmKolmogorow(xP, yP, xF, yF, Eps, vctrX, vctrY)*Eps; 

    return 0; 
} 
//*************************************************** 
unsigned long algorithmKolmogorow(double xp, double yp, double xf, 
double yf, const double eps, vector<double> &vectorX, vector<double> &vectorY) 
{ 
    static unsigned long N; //licznik 
    static unsigned long i = 1; 
    double d; 
    double a,b; 

     d = Pitagoras(xp, yp, xf, yf); 

     if(d >= eps){ 
      a = (yf - yp)/(xf - xp); 
      b = yp - a*xp; 
      xp = calculateX(xp, yp, a, b, eps); 
      yp = calculateY(xp, a, b); 
      N++; 
     } 

      else{ 
      i++; 
      xf = vectorX[i]; 
      yf = vectorY[i]; 
      //cout<<i<<"\t"<<vectorX[i]<<"\t"<<vectorY[i]<<endl; 
      } 

      if(i < vectorX.size()) 
       N = algorithmKolmogorow(xp, yp, xf, yf, eps, vectorX, vectorY); 

return N; 
} 

В основной, как вы можете видеть, я устанавливаю х, у координаты для параболической функции. Когда Eps большой, например Eps = 0.001, все работает. Если я устанавливаю меньшее значение, например Eps = 0.0001, то я получаю ошибку, как при остановке темы и программы. Я совершенно не понимаю, почему.

Я могу добавить любую новую информацию, которая вам нужна (о моем компиляторе, IDE, ОС и т. Д.).

Рафал

+0

Вы никогда не получаете доступ к первым или вторым элементам 'vectorX' или' vectorY'. Это намеренно?Обратите внимание, что 'xf = vectorX [i]' всегда будет пытаться получить доступ к третьему элементу, потому что 'i' начинается с' 1'. Помните, что векторы индексируются 0. – AndyG

+0

Когда я запускаю это, статическая переменная 'i' в' algorithmKolmogorow' никогда не увеличивается, поэтому блок 'if' в конце всегда вычисляет true и приводит к бесконечной рекурсии. – Carlton

+0

В основной функции я устанавливаю vectorX [0] и vectorX [1] для переменных xP и xF. И я начал с значения i = 2, потому что перед кодом, который вы указали, является инкрементным i ++ –

ответ

1

Вероятно, из-за рекурсии выбегает из пространства стека.

Быстрый взломать это, чтобы поднять размер стека с помощью ulimit в оболочке, например.

(ulimit -s unlimited; ./my_program) 

Настоящим решением является удаление рекурсии. algorithmKolmogorow выглядит как это делает только хвост рекурсии, которые всегда могут быть преобразованы в петлю:

unsigned long algorithmKolmogorow(double xp, double yp, double xf, 
double yf, const double eps, vector<double> &vectorX, vector<double> &vectorY) 
{ 
    static unsigned long N; //licznik 
    static unsigned long i = 1; 
    double d; 
    double a,b; 

    while(true) { 
     d = Pitagoras(xp, yp, xf, yf); 

     if(d >= eps){ 
      a = (yf - yp)/(xf - xp); 
      b = yp - a*xp; 
      xp = calculateX(xp, yp, a, b, eps); 
      yp = calculateY(xp, a, b); 
      N++; 
     } 

      else{ 
      i++; 
      if(i >= vectorX.size()) 
       return N; 
      xf = vectorX[i]; 
      yf = vectorY[i]; 
      //cout<<i<<"\t"<<vectorX[i]<<"\t"<<vectorY[i]<<endl; 
      } 

    } 

} 

Там также устраняет проблему доступа векторов один элемент сдавших границы.

Есть еще некоторые проблемы:

  • N должны быть инициализированы
  • algorithmKolmogorow может быть использован только один раз в программе вызова. Удалите static от N и i, чтобы исправить это.
+0

ОК, когда мы устанавливаем цикл while, это действительно работает, но я не могу понять, почему N и i не могут быть статическими? Если есть статические, программа работает правильно. –

+0

@ RafałApriasz Попробуйте использовать алгоритм Kolmogorow дважды в строке, используя разные входные данные. Например. используйте 'vctrY.push_back (0.5 * x * x); // f (x) = (x^2)/2' второй раз для инициализации (не забудьте 'vctrX.clear(); vctrY.clear();' удалить старые значения). Если вы закомментируете первый вызов алгоритма Kolmogorow, вы получите около 12.7508 с новыми входными данными. Если вы прокомментируете первый вызов, вы получите 24.3852 за это (как изначально), но вы получите 24.3866 для второго вызова вместо 12.7508. –

1
  i++; 
     xf = vectorX[i]; 
     yf = vectorY[i]; 
     //cout<<i<<"\t"<<vectorX[i]<<"\t"<<vectorY[i]<<endl; 
     } 

     if(i < vectorX.size()) 

Это будет превышать пределы вектора на 1. Может быть, вам нужно if(i < vectorX.size()-1) или (отмечая замечание AndyG) может быть, вы нуждались в i++ быть ниже этих двух видов использования i.

0

Ваша ценность для Eps слишком мала. Это приводит к тому, что алгоритм прогрессирует слишком медленно, а это означает, что вы закончите пространство стека до завершения вычисления. Я увеличил Eps до 0,005, и код работает нормально. Не уверен, что он дает правильный ответ; вам нужно будет проверить.

Кроме того, вам нужно изменить эти строки:

xf = vectorX[i]; 
yf = vectorY[i]; 

Для этого:

xf = vectorX[i-1]; 
yf = vectorY[i-1]; 

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

+0

Теперь, я удаляю комментарий от: // cout << i << "\ t" << vectorX [i] << "\ t" << vectorY [i] << endl; И остановка программы не в конце, а при значении i = 1674. Я проверил, что vectorX [1674] и vectorY [1674] имеют значения –

+0

Причина этого также в том, что у вас закончилось пространство стека. Ваш алгоритм приводит к большому количеству рекурсии, которая оставляет очень мало места в стеке для чего-либо еще. Как отметил @ ex-bart, вам действительно нужно устранить рекурсию, учитывая количество вызовов функций, которые вы делаете на 'algorithmKolmogorow'. – Carlton

Смежные вопросы