C++: VectorCalculation
Currently, besides abondon myself into the work, speech and volunteer, which I am always pursuing for. For the preparation for the future, I am studying c++. You know, just pure Al, or modellling would not be the ideal direction, instead, ai gonna be applied to certain field, like medicine discovery, finanicial service and so on. For me, my work is on auto driving so more would be on autonomy in the future. based on this, in autonomy, fluently writing, or at least being able to read c++ would be necessary.
- C++ allows the user to run the same program on different operating systems or interfaces.
- C++ allows low-level manipulation of data at a certain level, like memory management
- C++ can run faster than python, as it is self-compiled.
In general, Like this blog shared, as we move into areas like sensor fusion, localization, and control, we’ll focus more on C / C++.
Here I would like to share one exercise from Edition3: Programming Principles and Practise Using C++. The book pdf can be downloaded here.
It is exercise 11 in Chapter7. In this exercise, I get to know, some programming thinking.
Question:
Write a function that finds the largest and smallest element of a vector argument and also computs the mean and median. Do not use global variables. Either return a struct containing the results or pass them back through reference arguments. Which of the two ways of returning serveral result values do you prefer and why?
Obviously, it is a question to find the largest, smallest, mean and median in a vector, whose element would be double type.
The bruteforce way is to write 4 functions to solve them. However, it requires a struct or pass them through reference arguments, at the same time, we need to get some development on organising multiple functions skills.
-
struct
: a class type. Under this class type, all the attributes and member function would be public:struc <ClassName>{}
-
reference arguments: when vector is refered, it would be like
vector<element_type> vector_name&
, any modification would be refered to the original vectors
The first solution, is to build a class, in this class, the vector would be one attribute, then there are 4 member functions to solve this problem. So the code structure is like following
struct VectorCalculation{
vector<double>& w;
VectorCalculation(vector<double> w_par)
: w(w_par)
{
}
double VectorMean(){
.....
return mean;
}
double VectorStd(){
......
return std;
}
double VectorMax(){
......
return max;
}
double VectorMin(){
.......
return min;
}
};
After defining the class, then calling the member functions can solve the problem.
VectorCalculation vc(w_cur);
vc.VectorMean();
vc.VectorStd();
vc.VectorMax();
vc.VectorMin();
The advantage of this solution is
- No global variables
- The vector is passed through a reference arguments, so it would directly modify the vector itself.
- Everything is within the class block.**
Here class VectorCalculation
is initialized every time a new vector comes on. Every vector values have to be stored for every class, which would lead to memory explosion, if there are thousands of vectors coming in every seconds.
Then I am thinking about whether we can treat vector as an input (not an attribute in the class), instead, set the 4 values as an attribution. A class definition came up as the following,
struct VectorStats {
double smallest;
double largest;
double mean;
double median;
};
Then define a function, take the vector as an input, get the output as VectorStats
VectorStats calculate_stats(const vector<double>& data) {
VectorStats stats;
if (data.empty()) {
return stats; // Return an empty stats object for an empty vector
}
stats.smallest = data[0];
stats.largest = data[0];
double sum = 0;
for (double value : data) {
sum += value;
stats.smallest = min(stats.smallest, value);
stats.largest = max(stats.largest, value);
}
stats.mean = sum / data.size();
vector<double> sorted_data = data;
sort(sorted_data.begin(), sorted_data.end());
int n = sorted_data.size();
stats.median = (n % 2 == 0) ? (sorted_data[n / 2 - 1] + sorted_data[n / 2]) / 2 : sorted_data[n / 2];
return stats;
}
Inside this function, beside using the regular c++ expression like if, for, sort, there is a special expression:
stats.median = (n % 2 == 0) ? (sorted_data[n / 2 - 1] + sorted_data[n / 2]) / 2 : sorted_data[n / 2];
It is a brief for structure, which shows, if n%2==0
, then stats.median = (sorted_data[n / 2 - 1] + sorted_data[n / 2]) / 2
, else sorted_data[n / 2]
In the 2nd solution, beside the advantages in the previous one, it also avoid the memory issue related to vector saving. So would recommand this method to others!