Итак, у меня была проблема (не домашняя работа, не волнуйтесь), когда мне нужно было найти линию, которая лучше всего описывает набор точек, если это имеет смысл.Я придумал алгоритм, который:
Вычисляет наклон между каждой парой точек и получает среднее значение
Используя среднее значениенайденный на шаге 1, он находит средний перехват с осью y, проходя по всем точкам (y = mx + b, находит b)
Мы проверяем все значения m, b, которые находятся в диапазоне + -5 от среднего значения, найденного ранее, и затем получаем пару, у которой линия имеет наименьшую сумму расстояний до точек
Мы повторяем сколько угоднораз нам нравится, беря результат шага 3, а затем проверяя радиус + -0,5, а затем + -0,05 и т. д.
У меня есть два основных вопроса / проблемы для васесли вы можете помочь:
Есть ли способ сделать этот алгоритм более эффективным / точным в некотором смысле?И если да, то как?
Поскольку я довольно плохо знаком с OOP / C ++, не могли бы вы быстро разобраться и посмотреть, не сделал ли я какие-либо ошибки / неправильные вызовы в своем коде?
Большое спасибо за потраченное время!
#include <iostream>
#include <string>
using namespace std;
class Point {
private:
double x;
double y;
public:
Point() //default
{
x = 0;
y = 0;
}
Point(double xAxis, double yAxis)
{
x = xAxis;
y = yAxis;
}
double getX()
{
return x;
}
double getY()
{
return y;
}
void setX(double tx)
{
x = tx;
}
void setY(double ty)
{
y = ty;
}
double calcSlope(Point p2)
{
return (p2.getY() - y) / (p2.getX() - x);
}
};
class Line {
private:
double m;
double b;
public:
Line()
{
m = b = 0;
}
Line(double slope, double remain)
{
m = slope;
b = remain;
}
Line(Point p1, Point p2)
{
m = (p1.getY() - p2.getY()) / (p1.getX() - p2.getX());
b = p1.getY() - p1.getX() * m;
}
double getSlope()
{
return m;
}
double getB()
{
return b;
}
void setSlope(double slope)
{
m = slope;
}
void setB(double bb)
{
b = bb;
}
double dist(Point p)
{
double d = (double)abs(m*p.getX() - p.getY() + b) / sqrt(1 + m * m);
return d;
}
void avgLine(Point pArr[], int size)
{
double sum = 0;
for (int i = 0; i < size; i++)
{
for (int j = i+1; j < size; j++)
{
sum += pArr[i].calcSlope(pArr[j]);
}
}
sum /= ((size)*(size - 1) / 2);
double sumB = 0;
for (int i = 0; i < size; i++)
{
sumB += pArr[i].getY() - sum * pArr[i].getX();
}
sumB /= size;
m = sum;
b = sumB;
}
double sumDist(Point pArr[], int size)
{
double sum = 0;
for (int i = 0; i < size; i++)
{
sum += this->dist(pArr[i]);
}
return sum;
}
};
int main()
{
int accuracy, size;
double x, y, min, tmp;
cout << "Please choose number of points:" << endl;
cin >> size;
Point *pArr;
pArr = new Point[size];
cout << "Please choose accuracy 0 < d < 5, accuracy is 10^(-d)" << endl;
cin >> accuracy;
for (int i = 0; i < size; i++)
{
cout << "X value:" << endl;
cin >> x;
cout << "Y value:" << endl;
cin >> y;
pArr[i].setX(x);
pArr[i].setY(y);
}
Line avgL;
avgL.avgLine(pArr, size);
Line minL = avgL, tmpLine;
min = minL.sumDist(pArr, size);
for (int i = 1; i >= pow(10, -accuracy); i /= 10)
{
for (double startM = avgL.getSlope() - 5 * i; startM <= avgL.getSlope() + 5 * i; startM += i)
{
for (double startB = avgL.getB() - 5 * i; startB <= avgL.getB() + 5 * i; startB += i)
{
tmpLine.setSlope(startM);
tmpLine.setB(startB);
tmp = tmpLine.sumDist(pArr, size);
if (tmp < min)
{
tmp = min;
minL = tmpLine;
}
}
}
avgL = minL;
}
cout << "The line is: y = " << minL.getSlope() << "x + " << minL.getB() << endl;
}