Using the original values of a vector after manipulation - c++

I am trying to convert vector values that are received form a file into two different formats. After converting into first format and printing the vector out, I want to use the original "read in" values to convert them into the second format.
At the moment, it seems that the second conversion is happening on the already converted values. However, I don't understand why it doesn't convert back to the original value then? And ultimately, how can I use the original values of the vector for the second conversion so the
else {
GetType();
GetXArg();
GetYArg();
}
works for the second time?
Here is the code snippet:
void Force::convToP() //converts to polar
{
if (forceType == 'c')
{
SetType('p');
SetXArg(sqrt(xArg * xArg + yArg * yArg));
SetYArg(atan(yArg / xArg));
}
else {
GetType(); //just return type, xArg and yArg in their original form
GetXArg();
GetYArg();
}
}
void Force::convToC() //converts to cartesian
{
if (forceType == 'p') {
SetType('c');
SetXArg(xArg * cos(yArg));
SetYArg(xArg * sin(yArg));
}
else {
GetType();
GetXArg();
GetYArg();
}
}
and the main function:
while (file >> type >> x >> y) {
Force f(type, x, y);
force.push_back(f);
}
for (int i = 0; i < force.size(); ++i) {
force[i].printforce();
}
cout << "Forces in Polar form: " << endl;
for (int i = 0; i < force.size(); ++i)
{
force[i].convToP();
force[i].printforce();
}
cout << "Forces in Cartesian form: " << endl;
for (int i = 0; i < force.size(); ++i) {
force[i].convToC();
force[i].printforce();
}
finally, the output at the moment is:
p 10 0.5
c 12 14
p 25 1
p 100 0.8
c 50 50
p 20 3.14
c -100 25
p 12 1.14
Forces in Polar form: <-first conversion. All works fine
p 10 0.5
p 18.4391 0.649399
p 25 1
p 100 0.8
p 70.7107 0.61548
p 20 3.14
p 103.078 0.237941
p 12 1.14
Forces in Cartesian form:
c 8.77583 4.20736 <-works fine
c 14.6858 8.8806 <-why doesn't convert back to c 12 14/ how to use the original values of vector
c 13.5076 11.3662
c 69.6707 49.9787
c 57.735 33.3333
c -20 -0.0318509
c 100.173 23.6111
c 5.01113 4.55328
Press any key to continue . . .
Very new to this, been baffled for some time, so would really appreciate any help and advice.

You are modifying xArg and then using the modified value to convert yArg. You need to do both conversions before either modification.
void Force::convToP() //converts to polar
{
if (forceType == 'c')
{
forceType = 'p';
decltype(xArg) newX = sqrt(xArg * xArg + yArg * yArg);
decltype(yArg) newY = atan(yArg / xArg);
xArg = newX;
yArg = newY
}
// no else needed
}
void Force::convToC() //converts to cartesian
{
if (forceType == 'p') {
forceType = 'c';
decltype(xArg) newX = xArg * cos(yArg);
decltype(yArg) newY = xArg * sin(yArg);
xArg = newX;
yArg = newY
}
// no else needed
}
You can verify the correct values with std::complex
#include <complex>
#include <vector>
#include <iostream>
int main() {
std::vector<std::complex<double>> nums
{
std::polar<double>(10, 0.5),
std::complex<double>(12, 14),
std::polar<double>(25, 1),
std::polar<double>(100, 0.8),
std::complex<double>(50, 50),
std::polar<double>(20, 3.14),
std::complex<double>(-100, 25),
std::polar<double>(12, 1.14)
};
for (auto num : nums)
{
std::cout << num << " (" << std::abs(num) << ", " << std::arg(num) << ")\n";
}
}
(8.77583,4.79426) (10, 0.5)
(12,14) (18.4391, 0.86217)
(13.5076,21.0368) (25, 1)
(69.6707,71.7356) (100, 0.8)
(50,50) (70.7107, 0.785398)
(-20,0.0318531) (20, 3.14)
(-100,25) (103.078, 2.89661)
(5.01113,10.9036) (12, 1.14)

It's often helpful to break sub-operations down into small single-concern functions.
The compiler will optimise away all the redundant copies, loads and stores:
#include <cmath>
#include <tuple>
auto computed(double xArg, double yArg)
{
return
std::make_tuple(
std::sqrt(xArg * xArg + yArg * yArg),
std::atan(yArg / xArg));
}
void modify(double& xArg, double& yArg)
{
std::tie(xArg, yArg) = computed(xArg, yArg);
}

Without knowing exactly what GetXArg() etc. do, it appears that you are modifying your original forces when you call force[i].convToP();. So after this loop all the forces in your array are converted to polar. If all you want to do is print the polar and cartesian representations without changing the originals, you should generate copies of the forces:
cout << "Forces in Polar form: " << endl;
for (int i = 0; i < force.size(); ++i)
{
Force tmpForce = force[i];
tmpForce.convToP();
tmpForce.printforce();
}
etc.
Edit: Looks like #Aconcagua beat me to it.

Your conversion function obviously changes the object it operates on. Then you need to be aware that the index operator ([]) returns a reference to the object in the vector. If you do not want to modify the original object, you'll have to make a copy of:
for (int i = 0; i < force.size(); ++i)
{
auto copy = force[i]
copy.convToP();
copy.printforce();
}
Now, you can operate on the unchanged values in the second run. Assuming you don't need the original values afterwards any more, you can just leave the second loop as is, otherwise, make copies again...
All a little easier with range based for loop:
for(auto c : force)
{
c.convToP();
c.printforce();
}
for(auto& c : force)
// ^ if you don't need original values any more, can use reference now
{
c.convToC();
c.printforce();
}

Related

Finding the median value of a vector using C++

I'm a programming student, and for a project I'm working on, on of the things I have to do is compute the median value of a vector of int values and must be done by passing it through functions. Also the vector is initially generated randomly using the C++ random generator mt19937 which i have already written down in my code.I'm to do this using the sort function and vector member functions such as .begin(), .end(), and .size().
I'm supposed to make sure I find the median value of the vector and then output it
And I'm Stuck, below I have included my attempt. So where am I going wrong? I would appreciate if you would be willing to give me some pointers or resources to get going in the right direction.
Code:
#include<iostream>
#include<vector>
#include<cstdlib>
#include<ctime>
#include<random>
#include<vector>
#include<cstdlib>
#include<ctime>
#include<random>
using namespace std;
double find_median(vector<double>);
double find_median(vector<double> len)
{
{
int i;
double temp;
int n=len.size();
int mid;
double median;
bool swap;
do
{
swap = false;
for (i = 0; i< len.size()-1; i++)
{
if (len[i] > len[i + 1])
{
temp = len[i];
len[i] = len[i + 1];
len[i + 1] = temp;
swap = true;
}
}
}
while (swap);
for (i=0; i<len.size(); i++)
{
if (len[i]>len[i+1])
{
temp=len[i];
len[i]=len[i+1];
len[i+1]=temp;
}
mid=len.size()/2;
if (mid%2==0)
{
median= len[i]+len[i+1];
}
else
{
median= (len[i]+0.5);
}
}
return median;
}
}
int main()
{
int n,i;
cout<<"Input the vector size: "<<endl;
cin>>n;
vector <double> foo(n);
mt19937 rand_generator;
rand_generator.seed(time(0));
uniform_real_distribution<double> rand_distribution(0,0.8);
cout<<"original vector: "<<" ";
for (i=0; i<n; i++)
{
double rand_num=rand_distribution(rand_generator);
foo[i]=rand_num;
cout<<foo[i]<<" ";
}
double median;
median=find_median(foo);
cout<<endl;
cout<<"The median of the vector is: "<<" ";
cout<<median<<endl;
}
The median is given by
const auto median_it = len.begin() + len.size() / 2;
std::nth_element(len.begin(), median_it , len.end());
auto median = *median_it;
For even numbers (size of vector) you need to be a bit more precise. E.g., you can use
assert(!len.empty());
if (len.size() % 2 == 0) {
const auto median_it1 = len.begin() + len.size() / 2 - 1;
const auto median_it2 = len.begin() + len.size() / 2;
std::nth_element(len.begin(), median_it1 , len.end());
const auto e1 = *median_it1;
std::nth_element(len.begin(), median_it2 , len.end());
const auto e2 = *median_it2;
return (e1 + e2) / 2;
} else {
const auto median_it = len.begin() + len.size() / 2;
std::nth_element(len.begin(), median_it , len.end());
return *median_it;
}
There are of course many different ways how we can get element e1. We could also use max or whatever we want. But this line is important because nth_element only places the nth element correctly, the remaining elements are ordered before or after this element, depending on whether they are larger or smaller. This range is unsorted.
This code is guaranteed to have linear complexity on average, i.e., O(N), therefore it is asymptotically better than sort, which is O(N log N).
Regarding your code:
for (i=0; i<len.size(); i++){
if (len[i]>len[i+1])
This will not work, as you access len[len.size()] in the last iteration which does not exist.
std::sort(len.begin(), len.end());
double median = len[len.size() / 2];
will do it. You might need to take the average of the middle two elements if size() is even, depending on your requirements:
0.5 * (len[len.size() / 2 - 1] + len[len.size() / 2]);
Instead of trying to do everything at once, you should start with simple test cases and work upwards:
#include<vector>
double find_median(std::vector<double> len);
// Return the number of failures - shell interprets 0 as 'success',
// which suits us perfectly.
int main()
{
return find_median({0, 1, 1, 2}) != 1;
}
This already fails with your code (even after fixing i to be an unsigned type), so you could start debugging (even 'dry' debugging, where you trace the code through on paper; that's probably enough here).
I do note that with a smaller test case, such as {0, 1, 2}, I get a crash rather than merely failing the test, so there's something that really needs to be fixed.
Let's replace the implementation with one based on overseas's answer:
#include <algorithm>
#include <limits>
#include <vector>
double find_median(std::vector<double> len)
{
if (len.size() < 1)
return std::numeric_limits<double>::signaling_NaN();
const auto alpha = len.begin();
const auto omega = len.end();
// Find the two middle positions (they will be the same if size is odd)
const auto i1 = alpha + (len.size()-1) / 2;
const auto i2 = alpha + len.size() / 2;
// Partial sort to place the correct elements at those indexes (it's okay to modify the vector,
// as we've been given a copy; otherwise, we could use std::partial_sort_copy to populate a
// temporary vector).
std::nth_element(alpha, i1, omega);
std::nth_element(i1, i2, omega);
return 0.5 * (*i1 + *i2);
}
Now, our test passes. We can write a helper method to allow us to create more tests:
#include <iostream>
bool test_median(const std::vector<double>& v, double expected)
{
auto actual = find_median(v);
if (abs(expected - actual) > 0.01) {
std::cerr << actual << " - expected " << expected << std::endl;
return true;
} else {
std::cout << actual << std::endl;
return false;
}
}
int main()
{
return test_median({0, 1, 1, 2}, 1)
+ test_median({5}, 5)
+ test_median({5, 5, 5, 0, 0, 0, 1, 2}, 1.5);
}
Once you have the simple test cases working, you can manage more complex ones. Only then is it time to create a large array of random values to see how well it scales:
#include <ctime>
#include <functional>
#include <random>
int main(int argc, char **argv)
{
std::vector<double> foo;
const int n = argc > 1 ? std::stoi(argv[1]) : 10;
foo.reserve(n);
std::mt19937 rand_generator(std::time(0));
std::uniform_real_distribution<double> rand_distribution(0,0.8);
std::generate_n(std::back_inserter(foo), n, std::bind(rand_distribution, rand_generator));
std::cout << "Vector:";
for (auto v: foo)
std::cout << ' ' << v;
std::cout << "\nMedian = " << find_median(foo) << std::endl;
}
(I've taken the number of elements as a command-line argument; that's more convenient in my build than reading it from cin). Notice that instead of allocating n doubles in the vector, we simply reserve capacity for them, but don't create any until needed.
For fun and kicks, we can now make find_median() generic. I'll leave that as an exercise; I suggest you start with:
typename<class Iterator>
auto find_median(Iterator alpha, Iterator omega)
{
using value_type = typename Iterator::value_type;
if (alpha == omega)
return std::numeric_limits<value_type>::signaling_NaN();
}

Why does a map insert change the object member values?

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
class Car {
public:
Car( float costs, float speed) : costs(costs), speed(speed){};
float getSpeed() const {
return speed;
}
float getCosts() const {
return costs;
}
private:
float costs;
float speed;
};
class CarManager {
public:
CarManager(){};
void assignCars( std::vector<Car> &cars){
float costs = 1000.0;
float inc_costs = 700.0;
float inc_speed = 50.0;
for (size_t i = 0; i <= 10; ++i) {
float speed = 10.0;
std::vector<Car*> car_vec;
for (size_t j = 0; j < 5; ++j) {
if (j >= i) {
cars.push_back(Car(costs, speed));
car_vec.push_back(&cars.back());
}
speed += inc_speed;
}
car_storage.insert( {costs , car_vec } );
costs += inc_costs;
}
}
void print(){
for (const auto & p : car_storage) {
std::cout << "map[" << p.first << "] = ";
for (const auto & s : p.second) {
std::cout << "[" << s->getSpeed() <<", " << s->getCosts() << "] , ";
}
std::cout << std::endl;
}
}
private:
std::map<float, std::vector<Car*> > car_storage;
};
int main()
{
std::vector<Car> cars;
CarManager car_manager;
car_manager.assignCars(cars);
car_manager.print();
}
The printout somehow differs from what I expect. I push a Car with costs and speed into a vector [cars.push_back(Car(costs, speed))] and later push a pointer to this Car in a local vector of Car*: car_vec.push_back(&cars.back()). Next, I insert the key (costs) and the value (car_vec) into the map. When I print the map out, the values aren't correct anymore.
In the first case for example:
first loop i = 0, inner loop j, thus (j >= i) and I push_back a Car( 1000.0, 10.0). What's contained in the map, later on, is simply a Car(0,0). For the other cars, this applies as well, but they have some strange values.
map[1000] = [0, 0] , [0, 7.41086e-38] , [0, 7.41063e-38] , [0, 7.41064e-38] , [210, 1700] ,
map[1700] = [0, 7.41092e-38] , [0, 7.41094e-38] , [0, 7.41094e-38] , [210, 1700] ,
map[2400] = [110, 2400] , [160, 2400] , [210, 2400] ,
map[3100] = [160, 3100] , [210, 3100] ,
map[3800] = [210, 3800] ,
I have no clue what is going on. Debugging showed me, that the values have been ok until they get inserted into the map at car_storage.insert( {costs , car_vec } ).
What happens when you write this:
cars.push_back(Car(costs, speed))
car_vec.push_back(&cars.back())
? You create a Car and push it's copy to the cars vector. On the next line you push a pointer to the copy in this vector. Never do it! On any further operation with first vector's size change like push_back, clear and so on it may reallocate all it's content. I.e. it takes new memory fragment, copies values there, deletes the old one. Old pointers to it's content become invalid.

finding pi - using Machin's formula. Different iterations are giving same result

I've written a few programs to find pi, this one being the most advanced. I used Machin's formula, pi/4 = 4(arc-tan(1/5)) - (arc-tan(1/239)).
The problem is that however many iterations I do, I get the same result, and I can't seem to understand why.
#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
double arctan_series(int x, double y) // x is the # of iterations while y is the number
{
double pi = y;
double temp_Pi;
for (int i = 1, j = 3; i < x; i++, j += 2)
{
temp_Pi = pow(y, j) / j; //the actual value of the iteration
if (i % 2 != 0) // for every odd iteration that subtracts
{
pi -= temp_Pi;
}
else // for every even iteration that adds
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
double calculations(int x) // x is the # of iterations
{
double value_1, value_2, answer;
value_1 = arctan_series(x, 0.2);
value_2 = arctan_series(x, 1.0 / 239.0);
answer = (4 * value_1) - (value_2);
return answer;
}
int main()
{
double pi;
int iteration_num;
cout << "Enter the number of iterations: ";
cin >> iteration_num;
pi = calculations(iteration_num);
cout << "Pi has the value of: " << setprecision(100) << fixed << pi << endl;
return 0;
}
I have not been able to reproduce your issue, but here is a bit cleaned up code with a few C++11 idioms and better variable names.
#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;
// double arctan_series(int x, double y) // x is the # of iterations while y is the number
// then why not name the parameters accoringly? In math we usually use x for the parameter.
// prefer C++11 and the auto notation wherever possible
auto arctan_series(int iterations, double x) -> double
{
// note, that we don't need any temporaries here.
// note, that this loop will never run, when iterations = 1
// is that really what was intended?
for (int i = 1, j = 3; i < iterations; i++, j += 2)
{
// declare variables as late as possible and always initialize them
auto t = pow(x, j) / j;
// in such simple cases I prefer ?: over if-else. Your milage may vary
x += (i % 2 != 0) ? -t : t;
}
return x * 4;
}
// double calculations(int x) // x is the # of iterations
// then why not name the parameter accordingly
// BTW rename the function to what it is supposed to do
auto approximate_pi(int iterations) -> double
{
// we don't need all of these temporaries. Just write one expression.
return 4 * arctan_series(iterations, 0.2) - arctan_series(iterations, 1.0 / 239.0);
}
auto main(int, char**) -> int
{
cout << "Enter the number of iterations: ";
// in C++ you should declare variables as late as possible
// and always initialize them.
int iteration_num = 0;
cin >> iteration_num;
cout << "Pi has the value of: "
<< setprecision(100) << fixed
<< approximate_pi(iteration_num) << endl;
return 0;
}
When you remove my explanatory comments, you'll see, that the resulting code is a lot more concise, easier to read, and therefore easier to maintain.
I tried a bit:
Enter the number of iterations: 3
Pi has the value of: 3.1416210293250346197169164952356368303298950195312500000000000000000000000000000000000000000000000000
Enter the number of iterations: 2
Pi has the value of: 3.1405970293260603298790556436870247125625610351562500000000000000000000000000000000000000000000000000
Enter the number of iterations: 7
Pi has the value of: 3.1415926536235549981768144789384678006172180175781250000000000000000000000000000000000000000000000000
Enter the number of iterations: 42
Pi has the value of: 3.1415926535897940041763831686694175004959106445312500000000000000000000000000000000000000000000000000
As you see, I obviously get different results for different numbers of iterations.
That method converges very quickly. You'll get more accuracy if you start with the smallest numbers first. Since 5^23 > 2^53 (the number of bits in the mantissa of a double), probably the maximum number of iterations is 12 (13 won't make any difference). You'll get more accuracy starting with the smaller numbers. The changed lines have comments:
double arctan_series(int x, double y)
{
double pi = y;
double temp_Pi;
for (int i = 1, j = x*2-1; i < x; i++, j -= 2) // changed this line
{
temp_Pi = pow(y, j) / j;
if ((j & 2) != 0) // changed this line
{
pi -= temp_Pi;
}
else
{
pi += temp_Pi;
}
}
pi = pi * 4;
return pi;
}
For doubles, there is no point in setting precision > 18.
If you want an alternative formula that takes more iterations to converge, use pi/4 = arc-tan(1/2) + arc-tan(1/3), which will take about 24 iterations.
This is another way if some of you are interested. The loop calculates the integral of the function : sqrt(1-x²)
Which represents a semicircle of radius 1. Then we multiply by two the area. Finally we got the surface of the circle which is PI.
#include <iomanip>
#include <cmath>
#define f(x) sqrt(1-pow(x,2))
double integral(int a, int b, int p)
{
double d=pow(10, -p), s=0;
for (double x=a ; x+d<=b ; x+=d)
{
s+=f(x)+f(x+d);
}
s*=d/2.0;
return s;
}
int main()
{
cout << "PI=" << setprecision (9) << 2.0*integral(-1,1,6) << endl;
}

Do I need to check the pointer before using noalias in Eigen(c++)

Assume there are three matrix a,b,c
a and c share the same buffer but with different name
should do some check like
if(a.data() == c.data()){
a = b * c;
}else{
a.noalias() = b * c;
}
Or I could just write a = b + c?
Edit : full example
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
template<typename Derived>
void sigmoid(MatrixBase<Derived> const &input, MatrixBase<Derived> const &weight,
MatrixBase<Derived> &output)
{
output = weight * input;
output= 1.0 / (1.0 + (-1.0 * output.array()).exp());
}
int main()
{
MatrixXd weight = MatrixXd::Random(2, 2);
MatrixXd input = MatrixXd::Random(2, 2);
MatrixXd activation;
for(size_t i = 0; i != 2; ++i){
MatrixBase<MatrixXd> const &Temp =
i == 0 ? input : activation;
sigmoid(Temp , weight, activation);
}
}
The example already simplify, the case is, when i == 0, the Temp should be input, when it is not, it should be activation.
Your underlying assumption that the data pointers will match is incorrect. Just to prove that, try this:
Eigen::MatrixXd aa = Eigen::MatrixXd::Random(5,5);
Eigen::Map<Eigen::MatrixXd> gg(aa.data()+5, 4, 5);
std::cout << aa.data() << "\n";
std::cout << gg.data() << "\n";
So, you would have to either know at compile time if they share the same buffer or not (or think of a better test). With the limited example shown, I think you'll have to write a = b * c just to make sure a and c don't overlap.

Dereferencing object array pointer in C++

I have this small question about dereferencing arrays. I have a method in class like this
T* foo()
{
// create specific array of objects in here
return (array)
}
foo2()
{
myNewArray = *foo();
// exactly the same algorithm as in foo to create checkArray
cout << sizeof(myNewArray) << sizeof(checkArray) << endl;
}
I get two different results, but I expect them to be the same?
Ok, so the additional information about the code:
vec4* getGridAttr()
{
float xval = -0.5;
float yval = -0.75;
float xval2 = -0.5;
float yval2 = -0.75;
vec4 pointsGrid[100];
for (int i=0;i<42;i++)
{
//Draw horizontal lines
if (i % 2 == 0) pointsGrid[i] = vec4(xval, yval, 0.0,1);
else if (i % 2 != 0) {
pointsGrid[i] = vec4((xval+0.75), yval, 0.0,1);
yval += 0.075;
}
}
for (int j=42;j<64;j++)
{
//Draw horizontal lines
if (j % 2 != 0)
{
pointsGrid[j] = vec4(xval2, yval2, 0.0,1);
xval2 += 0.075;
}
else if (j % 2 == 0) {
pointsGrid[j] = vec4(xval2, -yval2, 0.0,1);
}
}
return (pointsGrid);
}
and in my other method, i have this:
void display( void )
{
vec4 points1[100];
//code here populates points1 exactly the same as in getGridAttributes,
cout << "points1 : " << sizeof(points1) << " " << " pointsFromGridAttr : " << sizeof(*getGridAttr()) << endl;
}
The output is points1 : 1600 pointsFromGridAttr 16
Without seeing more code I can't be sure of this, but if you have something like this:
T* arr1 = makeArray();
T arr2[n];
Then arr1 and arr2 would have different sizes. Specifically, arr1 is a pointer, so its size is the size of a pointer, while arr2 is an array, and its size will be the size of a T object times the number of objects in the array.
Although arrays and pointers in C++ can be interchanged in some contexts, they really are different types. T* and T [n] are different types with different sizes. Once an array decays to a pointer, it loses its size information.
Hope this helps!
I guess you would like to compare the length of the arrays. The length of a C array should be calculated as sizeof(array_variable) / sizeof(type_of_array_elements) or sizeof(array_variable) / sizeof(one_element), not just as sizeof(array_variable). For details see this SO question.
Try this:
cout << sizeof(myNewArray) / sizeof(myNewArray[0]) << ", " << sizeof(checkArray) / sizeof(checkArray[0]) << endl;