Действительно, алгоритм adjacent_difference
логически нарушен (почему должна быть разница в одном и том же времени элементов? Почему первый выходной элемент равен первому, а не получается, что выходная последовательность на один элемент короче, чем входная)(более логично)?
В любом случае, я не понимаю, почему вы наказываете себя, используя функциональный подход с C ++, в котором ясно, что код будет труднее писать, труднее читать, медленнее компилировать ине быстрее, чтобы выполнить. Ох .. и давайте не будем говорить о том типе сообщения об ошибке шутки, с которым вы столкнетесь, если есть какая-то ошибка в том, что вы вводите.
Что плохого в
std::vector<double> distances;
for (int i=1,n=points.size(); i<n; i++)
distances.push_back(magnitude(points[i] - points[i-1]));
?
Это короче, удобочитаемее, быстрее компилируется и может быть еще быстрее.
РЕДАКТИРОВАТЬ
Я хотел проверить свой субъективный «короче, удобочитаемее, быстрее компилируется и быстрее исполняется». Вот результаты:
~/x$ time for i in {1..10}
> do
> g++ -Wall -O2 -o algtest algtest.cpp
> done
real 0m2.001s
user 0m1.680s
sys 0m0.150s
~/x$ time ./algtest
real 0m1.121s
user 0m1.100s
sys 0m0.010s
~/x$ time for i in {1..10}
> do
> g++ -Wall -O2 -o algtest2 algtest2.cpp
> done
real 0m1.651s
user 0m1.230s
sys 0m0.190s
~/x$ time ./algtest2
real 0m0.941s
user 0m0.930s
sys 0m0.000s
~/x$ ls -latr algtest*.cpp
-rw-r--r-- 1 agriffini agriffini 932 2011-11-25 21:44 algtest2.cpp
-rw-r--r-- 1 agriffini agriffini 1231 2011-11-25 21:45 algtest.cpp
~/x$
Ниже приводится приемлемое решение (я исправляюd, что, очевидно, является умственной передачей вектора точек по значению).
// ---------------- algtest.cpp -------------
#include <stdio.h>
#include <math.h>
#include <functional>
#include <algorithm>
#include <vector>
using std::vector;
using std::ptr_fun;
struct Point
{
double x, y;
Point(double x, double y) : x(x), y(y)
{
}
Point operator-(const Point& other) const
{
return Point(x - other.x, y - other.y);
}
};
double magnitude(const Point& a)
{
return sqrt(a.x*a.x + a.y*a.y);
}
double point_distance(const Point& a, const Point& b)
{
return magnitude(b - a);
}
vector<double> adjacent_distances( const vector<Point>& points ) {
if ( points.empty() ) return vector<double>();
vector<double> distances(
1, point_distance( *points.begin(), *points.begin() ) );
std::transform( points.begin(), points.end() - 1,
points.begin() + 1,
std::back_inserter(distances),
ptr_fun( point_distance ) );
return distances;
}
int main()
{
std::vector<Point> points;
for (int i=0; i<1000; i++)
points.push_back(Point(100*cos(i*2*3.141592654/1000),
100*sin(i*2*3.141592654/1000)));
for (int i=0; i<100000; i++)
{
adjacent_distances(points);
}
return 0;
}
Вот вместо этого явное решение цикла;требуется, чтобы два включали меньше, одно определение функции меньше, а тело функции также короче.
// ----------------------- algtest2.cpp -----------------------
#include <stdio.h>
#include <math.h>
#include <vector>
struct Point
{
double x, y;
Point(double x, double y) : x(x), y(y)
{
}
Point operator-(const Point& other) const
{
return Point(x - other.x, y - other.y);
}
};
double magnitude(const Point& a)
{
return sqrt(a.x*a.x + a.y*a.y);
}
std::vector<double> adjacent_distances(const std::vector<Point>& points)
{
std::vector<double> distances;
if (points.size()) distances.reserve(points.size()-1);
for (int i=1,n=points.size(); i<n; i++)
distances.push_back(magnitude(points[i] - points[i-1]));
return distances;
}
int main()
{
std::vector<Point> points;
for (int i=0; i<1000; i++)
points.push_back(Point(100*cos(i*2*3.141592654/1000),
100*sin(i*2*3.141592654/1000)));
for (int i=0; i<100000; i++)
{
adjacent_distances(points);
}
return 0;
}
Резюме:
- размер кода короче (algtest2.cpp меньше 76% от algtest.cpp)
- время компиляции лучше (algtest2.cpp требует менее 83% от algtest.cpp)
- время выполнения лучше (algtest2.cpp работает менее чем на 85%of algtest.cpp)
Так что, очевидно, в моей системе (не отобранной) я был прав по всем пунктам, кроме скорости выполнения (с «возможно»), где можно перейти от немного медленнее к существеннобыстрее я должен был вызвать reserve
в массиве результатов.Даже с этой оптимизацией код, конечно, короче.
Я также думаю, что тот факт, что эта версия более читабельна, также объективен, а не является мнением ... но я был бы рад оказаться неправымвстреча с кем-то, кто может понять, что делает функциональная вещь, и кто не может понять, что вместо этого делает явная.