I am aware there exists a C++ function template (std::inner_product), but I want to try writing my own. Here's some code I found but it runs in the main function:
#include <iostream>
using namespace std;
int main(){
float vectorA[3], vectorB[3], scalar=0.0;
int i;
// Get input vectors from user.
cout << "Enter elements of first vector: " << endl;
for(i=0;i<3;i++)
{
cin >> vectorA[i];
}
cout << "Enter elements of second vector: " << endl;
for(i=0;i<3;i++)
{
cin >> vectorB[i];
}
// Calculate scalar product.
for(i=0;i<3;i++)
{
scalar = scalar + (vectorA[i] * vectorB[i]);
}
// Output result.
cout << "The scalar product is " << scalar << endl;
return 0;
}
Next, I want to write this into a separate reusable function that I can call from my main loop. This is the best I could come up with.
float scalarProduct(float a1, float a2, float a3, float b1, float b2, float b3) {
float vectorA[3], vectorB[3], scalar;
vectorA[0]=a1;
vectorA[1]=a2;
vectorA[2]=a3;
vectorB[0]=b1;
vectorB[1]=b2;
vectorB[2]=b3;
for(int i=0;i<3;i++) // Calculate scalar product.
{
scalar = scalar + (vectorA[i] * vectorB[i]);
}
return scalar;
}
int main() {
cout << scalarProduct(1,2,3,4,5,6);
}
So my questions are:
How can I pass an array into this function? There must be a better way than having six parameters but I can't figure out how.
When I run the program in Xcode, I get the warning 'Variable scalar may be uninitialised when used here' at the line
scalar = scalar + (vectorA[i] * vectorB[i]);
The program still runs and computes the correct answer but how can I make this warning go away?
Question
How can I pass an array into this function? There must be a better way than having six parameters but I can't figure out how.
Change the function to accept two arrays as argument. For the sake of safety, also pass the number of elements in the array.
float scalarProduct(float a[], float b[], size_t num);
Change the function to accept two std:vectors as argument.
float scalarProduct(std::vector<float> const& a, std::vector<float> const& b);
Change the function to accept two std:arrays as argument.
float scalarProduct(std::array<float, 3> const& a, std::array<float, 3> const& b);
In all of these cases, you can access the elements of the collection using the array syntax.
float scalarProduct(std::array<float, 3> const& a, std::array<float, 3> const& b)
{
// Initialize scalar to 0
float scalar = 0.0f;
for(int i=0;i<3;i++) // Calculate scalar product.
{
scalar = scalar + (a[i] * b[i]);
}
return scalar;
}
The implementations will be a little different if you use the other signatures but not too different.
Question
When I run the program in Xcode, I get the warning 'Variable scalar may be uninitialised when used here' at the line
I have already added the line to initialize scalar. Without that, the initial value of scalar is not predictable. Also, accessing the value of an uninitialized variable is cause of undefined behavior.
How can I pass an array into this function? There must be a better way than having six parameters but I can't figure out how.quote
To pass an array into your function, simply do:
float scalarProduct(float arr[6])
In your main(), it will look like:
float array[6] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
cout << scalarProduct(array);
From there you can use your array like:
vectorA[0]=arr[0];
vectorA[1]=arr[1];
vectorA[2]=arr[2];
vectorB[0]=arr[3];
vectorB[1]=arr[4];
vectorB[2]=arr[5];
When I run the program in Xcode, I get the warning 'Variable scalar may be uninitialised when used here' at the line
Maybe try and initialize scalar with an initial value:
float scalar = 0.0;
Just have your function take in a reference to a vector (or array as stated by Hayden). A vector is better as you don't have to hard-code the size of the vector.
Also, it is useful to have a template function for this case.
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
T scalarProduct(const vector<T>& a, const vector<T>& b)
{
// Check that the size of a and b match here.
// If not, do what you deem is necessary.
T product = 0; // Not initializing variable is cause of your warning.
for (int i = 0; i < a.size(); i++)
product += a[i] * b[i];
return product;
}
int main(void)
{
// Compile for c++ 11
// vector<float> a = {1.0, 2.0, 3.0};
// vector<float> b = {1, 1, 1};
// Else
vector<float> a;
vector<float> b;
a.push_back(1);
a.push_back(2);
a.push_back(3);
b.push_back(1);
b.push_back(1);
b.push_back(1);
cout << scalarProduct<float>(a, b) << endl;
return 0;
}
Related
I stumbled upon the following code segment somewhere to create a list of random numbers in a certain interval:
#include <vector>
#include <iostream>
#include <math.h>
struct gen_rand_pos{
double factor;
public:
gen_rand_pos(double r=1.0): factor(r/RAND_MAX)
{}
double operator()(){
return rand()*factor;
}
};
int main(){
int N = 5;
std::vector<double> result(N);
std::generate_n(std::back_inserter(result), N, gen_rand_pos(1.0));
std::cout << result[0] << std::endl;
}
It works perfectly fine. I tried to take this one step further and do the same, but this time creating a list(vector) of random unit vectors, uniformly distributed on the sphere. Here is my go at this:
double l2_norm(std::vector<double> const& u) {
double accum = 0.;
for (double x : u) {
accum += x * x;
}
return sqrt(accum);
}
struct gen_rand_vec{
double factor;
public:
gen_rand_vec(): factor(2.0/RAND_MAX)
{}
std::vector<double> operator()(){
std::vector<double> result = {rand()*factor-1,rand()*factor-1,rand()*factor-1}; // uniform in each component
double norm = l2_norm(result);
std::transform(result.begin(), result.end(), result.begin(),
std::bind1st(std::multiplies<float>(),1/norm)); // normalize the vector
return result;
}
};
However if I now try to construct it in the same manner:
int main(){
int N = 5;
std::vector<std::vector<double>> result2(N);
std::generate_n(std::back_inserter(result2), N, gen_rand_vec());
std::cout << result2[0][0] <<std::endl;
}
I get a segmentation error. Is the problem lying in the back_inserter or am I doing something completely wrong? I can't figure out. I checked the construction of the single vectors and they work just fine, so the mistake has to lie somewhere after that.
Thanks in advance.
Default size of inner vectors for result2 for indices <0,4> is 0, so you cannot access
result2[0][0] // inner vector doesn't keep any elements
when you call generate_n with back_inserter, you add new vectors to the end of result2. In this case you can access indices of inner vector for result2[>=5].
Your problem is quite simple, std::back_inserter is inserting new vectors at the end of result2. Hence, you cannot access the first element, since it is not initialized. To solve this, just remove the (N) from the initialization of result2. Example.
I am confused on how would i Print out all the elements in aVect and bVect. From my understanding, inside of the int main the float FloatArray1 holds 10 spots, which are all filled up with the numbers inside of the {} next to it. Afterwards, that Array and the array size, which is 10, is being passed into a class object named aVect.
What I am confused is, how would I print the elements in aVect when nothing is being passed to the void printElement function? From what I was taught about arrays, if it was something like
int array[5] = {1,2,3,4,5}
for (int i =0; i < 5; i++)
{cout << array[i] << endl;}
But then that only works because is it directly in the same scope of code. In the code below, the printElements function will be used for both aVect and bVect so it can't be passed specifically by reference and can't be done like the way above. Could anyone help me try to figure this? Barely learning the basics of classes and functions.
class FloatVectArray {
public:
void printElements(); // prints all elements in the vector
private:
float *vector; // the vector
int vectorsize; // size of the vector
void FloatVectArray::printElements()
{
for (int i = 0; i < 10; i++)
{
cout << << endl;
}
}
int main() {
// testing the implementation of a float vector using array
// declare & initialize an array of floats and create a float vector aVect
float FloatArray1[10] = { 2.1, 7.2, 3.3, 6.4, 1.5, 43.6,72.7,19.8,39.9, 71.1 };
FloatVectArray aVect(FloatArray1, 10);
cout << "Printing all elements in aVect:" << endl;
aVect.printElements();
// declare & initialize another array of floats and create float vector bVect
float FloatArray2[10] = { 1.1, 2.2, 5.3, 6.4, 1.5, 7.6, 9.7,17.8, 92.9, 42.1 };
FloatVectArray bVect(FloatArray2, 10);
cout << "Printing all elements in bVect:" << endl;
bVect.printElements();
If I understand your question right, the thing you are missing is that because its
void FloatVectArray::printElements()
and not
void printElements()
the members of the class FloatVectArray are in scope for body of the function. You can simply access them by their name:
cout << vector[i] << endl;
if you really wanted you could explicitly scope the member variable:
cout << FloatVectArray::vector[i] << endl;
but that is not necessary in this case.
Better to adjust the for-loop accordingly of course
for (int i = 0; i < vectorsize; i++)
If I understand you right, your aim is this understanding classes thing but anyway two more hints:
If you simply copy the pointer to the array, like I did in the completed code below, your FloatVectArray will have a dangling pointer if the passed-in array expires, thats bad
start working with well-thougt whitespace from the beginning. It makes your code easier to read and frees brain capacity for more important thing.
completed code for your reference:
#include <iostream>
class FloatVectArray {
public:
FloatVectArray(float* v, int size) :vector(v), vectorsize(size) {};
void printElements(); // prints all elements in the vector
private:
float *vector; // the vector
int vectorsize; // size of the vector
};
void FloatVectArray::printElements()
{
for (int i = 0; i < vectorsize; i++)
{
std::cout << vector[i] << std::endl;
}
}
int main(int argc, const char * argv[]) {
// testing the implementation of a float vector using array
// declare & initialize an array of floats and create a float vector aVect
float FloatArray1[10] = { 2.1, 7.2, 3.3, 6.4, 1.5, 43.6,72.7,19.8,39.9, 71.1 };
FloatVectArray aVect(FloatArray1, 10);
std::cout << "Printing all elements in aVect:" << std::endl;
aVect.printElements();
// declare & initialize another array of floats and create float vector bVect
float FloatArray2[10] = { 1.1, 2.2, 5.3, 6.4, 1.5, 7.6, 9.7,17.8, 92.9, 42.1 };
FloatVectArray bVect(FloatArray2, 10);
std::cout << "Printing all elements in bVect:" << std::endl;
bVect.printElements();
return 0;
}
I am wondering why this wont recognize the vector is empty and supply vector pStack with double start? The object of the program is just to simply supply the stack vector with 50 the first time around when it is empty. Then once it is supplied with the starting amount it should subtract with the user input (being bet). Then since its a vector it carries over the old sum into the 2nd time around so it can be subtracted with the user input of bet again.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Bet
{
public:
void set_stack(double n);
void set_bet(double n);
double analyze();
double get_stack();
double get_bet();
private:
double pCount;
double bet;
};
double Bet::analyze()
{
double p = pCount;
double b = bet;
double z = p - b;
return z;
}
void Bet::set_bet(double n)
{
bet = z;
}
double Bet::get_bet()
{
return bet;
}
void Bet::set_stack(double n)
{
pCount = n;
}
double Bet::get_stack()
{
return pCount;
}
double start = 50; // Start needs to go inside of pStack
double bbet;
vector<double> pStack(1);
int main()
{
bool con = true;
while(con){
if(pStack.empty()){
pStack.push_back(start); // pStack should be supplied with start when empty
}
double adjst = pStack[0];
Bet rr;
rr.set_stack(adjst);
pStack.clear();
cout << "Enter min 1 Bet: ";
cin >> bbet;
rr.set_bet(bbet);
double aStack = rr.analyze();
pStack.push_back(aStack);
rr.set_stack(aStack);
double newStack = rr.get_stack();
cout << "Stack: " << newStack << endl;
cout << "Bet: " << bbet << endl;
}
system("pause");
return 0;
}
vector<double> pStack(1);
You are initializing your vector with it having an initial size of 1, that's why your pStack.empty() check returns false.
Do this instead to make its initial state empty.
vector<double> pStack;
Also, remove the empty() check and hoist your push_back outside your while loop.
bool con = true;
pStack.push_back(start);
while(con){
...
You might also want to reconsider your usage of global variables. As far as I can see, you can just put start, bbet and pStack inside main().
You are using the fill constructor. This line will initialize the vector to 1 element, default constructed.
vector<double> pStack(1);
If you wanted the vector to start out empty, you should just use the default constructor.
vector<double> pStack;
When you define the pStack vector you use the constructor that takes an integer that represent the number of elements to allocate.
vector<double> pStack(1);
As a result your vector will have 1 default-initialized element.
To create an empty vector do this:
vector<double> pStack;
So I am a new to this. I am trying to write a program with a function
double_product(vector< double > a, vector< double > b) that computes the scalar product of two vectors. The scalar product is
$a_{0}b_{0}+a_{1}b_{1}+...a_{n-1}b_{n-1}$.
Here is what I have. It is a mess, but I am trying!
#include<iostream>
#include<vector>
using namespace std;
class Scalar_product
{
public:
Scalar_product(vector<double> a, vector<bouble> b);
};
double scalar_product(vector<double> a, vector<double> b)
{
double product = 0;
for (int i=0; i <=a.size()-1; i++)
for (int i=0; i <=b.size()-1; i++)
product = product + (a[i])*(b[i]);
return product;
}
int main()
{
cout << product << endl;
return 0;
}
You have a pretty correct idea, at the fundamental level. A couple of basic building blocks extra and you'll be well on your way. Your scalar_product function is close, but not quite. You've created two loop iterators with the same name iterating over the same values. It should be fine to simply say
if (a.size() != b.size()) {} // error
for (int i=0; i < a.size(); i++)
product = product + (a[i])*(b[i]);
Now all you have to do is get some data, call it, and then output the result.
int main() {
std::vector<double> a;
std::vector<double> b;
// fill with the values
std::cout << scalar_product(a, b) << endl;
}
The whole class thing is completely unnecessary here- the only classes you need come in the Standard lib.
since I cannot comment I am forced to reply.
apparently there is exactly the same question, word by word, here:
Computing the scalar product of two vectors in C++
I am trying to write a program with a function double_product(vector<double> a, vector<double> b) that computes the scalar product of two vectors. The scalar product is
$a_{0}b_{0}+a_{1}b_{1}+...+a_{n-1}b_{n-1}$.
Here is what I have. It is a mess, but I am trying!
#include <iostream>
#include <vector>
using namespace std;
class Scalar_product
{
public:
Scalar_product(vector<double> a, vector<double> b);
};
double scalar_product(vector<double> a, vector<double> b)
{
double product = 0;
for (int i = 0; i <= a.size()-1; i++)
for (int i = 0; i <= b.size()-1; i++)
product = product + (a[i])*(b[i]);
return product;
}
int main() {
cout << product << endl;
return 0;
}
Unless you need to do this on your own (e.g., writing it is homework), you should really use the standard algorithm that's already written to do exactly what you want:
#include <iostream>
#include <numeric>
#include <vector>
int main() {
std::vector<double> a {1, 2, 3};
std::vector<double> b {4, 5, 6};
std::cout << "The scalar product is: "
<< std::inner_product(std::begin(a), std::end(a), std::begin(b), 0.0);
return 0;
}
Note that while begin(a) and end(a) are new in C++11, std::inner_product has been available since C++98. If you are using C++ 98 (or 03), it's pretty easy to write your own equivalent of begin and end to work with arrays though:
template <class T, size_t N>
T *begin(T (&array)[N]) {
return array;
}
template <class T, size_t N>
T *end(T (&array)[N]) {
return array + N;
}
Using these, a C++ 98 version of the previous code could look something like this:
int main() {
double a[] = {1, 2, 3};
double b[] = {4, 5, 6};
std::cout << "The scalar product is: "
<< std::inner_product(begin(a), end(a), begin(b), 0.0);
return 0;
}
Note that the begin and end above will only work for arrays, where the begin and end in C++11 (and later) will also work for normal collection types that define a .begin() and .end() (though it's trivial to add overloads to handle those as well, of course):
template <class Coll>
typename Coll::iterator begin(Coll const& c) { return c.begin(); }
template <class Coll>
typename Coll::iterator end(Coll const& c) { return c.end(); }
You can delete the class you have defined. You don't need it.
In your scalar_product function:
double scalar_product(vector<double> a, vector<double> b)
{
double product = 0;
for (int i = 0; i <= a.size()-1; i++)
for (int i = 0; i <= b.size()-1; i++)
product = product + (a[i])*(b[i]);
return product;
}
It's almost there. You don't need 2 loops. Just one.
double scalar_product(vector<double> a, vector<double> b)
{
if( a.size() != b.size() ) // error check
{
puts( "Error a's size not equal to b's size" ) ;
return -1 ; // not defined
}
// compute
double product = 0;
for (int i = 0; i <= a.size()-1; i++)
product += (a[i])*(b[i]); // += means add to product
return product;
}
Now to call this function, you need to create 2 vector objects in your main(), fill them with values, (the same number of values of course!) and then call scalar_product( first_vector_that_you_create, second_vector_object );
While you have been presented many solutions that work, let me spin up another variation to introduce a couple of concepts that should help you writing better code:
class are only needed to pack data together
a function should check its preconditions as soon as possible, those should be documented
a function should have postconditions, those should be documented
code reuse is the cornerstone of maintenable programs
With that in mind:
// Takes two vectors of the same size and computes their scalar product
// Returns a positive value
double scalar_product(std::vector<double> const& a, std::vector<double> const& b)
{
if (a.size() != b.size()) { throw std::runtime_error("different sizes"); }
return std::inner_product(a.begin(), a.end(), b.begin(), 0.0);
} // scalar_product
You could decide to use the inner_product algorithm directly but let's face it:
it requires four arguments, not two
it does not check for its arguments being of the same size
so it's better to wrap it.
Note: I used const& to indicate to the compiler not to copy the vectors.
You seem to want to make a class specifically for vectors. The class I made in my example is tailored to 3 dimensional vectors, but you can change it to another if desired. The class holds i,j,k but also can conduct a scalar products based on other MathVectors. The other vector is passed in via a C++ reference. It is hard to deduce what the question was, but I think this might answer it.
#include <iostream>
using namespace std;
class MathVector
{
private:
double i,j,k;
public:
MathVector(double i,double j,double k)
{
this->i=i;
this->j=j;
this->k=k;
}
double getI(){return i;}
double getJ(){return j;}
double getK(){return k;}
double scalar(MathVector &other)
{
return (i*other.getI())+(j*other.getJ())+(k*other.getK());
}
};
int main(int argc, char **argv)
{
MathVector a(1,2,5), b(2,4,1);
cout << a.scalar(b) << endl;
return 0;
}
Here is the code that you should have. I see you have used class in your code, which you do not really need here. Let me know if the question required you to use class.
As you are new and this code might scare you. So, I will try to explain this as I go. Look for comments in the code to understand what is being done and ask if you do not understand.
//Scalar.cpp
#include <stdlib.h>
#include <iostream>
#include <vector>
using namespace std;
/**
This function returns the scalar product of two vectors "a" and "b"
*/
double scalar_product(vector<double> a, vector<double> b)
{
//In C++, you should declare every variable before you use it. So, you declare product and initialize it to 0.
double product = 0;
//Here you check whether the two vectors are of equal size. If they are not then the vectors cannot be multiplied for scalar product.
if(a.size()!=b.size()){
cout << "Vectors are not of the same size and hence the scalar product cannot be calculated" << endl;
return -1; //Note: This -1 is not the answer, but just a number indicating that the product is not possible. Some pair of vectors might actually have a -1, but in that case you will not see the error above.
}
//you loop through the vectors. As bobo also pointed you do not need two loops.
for (int i = 0; i < a.size(); i++)
{
product = product + a[i]*b[i];
}
//finally you return the product
return product;
}
//This is your main function that will be executed before anything else.
int main() {
//you declare two vectors "veca" and "vecb" of length 2 each
vector<double> veca(2);
vector<double> vecb(2);
//put some random values into the vectors
veca[0] = 1.5;
veca[1] = .7;
vecb[0] = 1.0;
vecb[1] = .7;
//This is important! You called the function you just defined above with the two parameters as "veca" and "vecb". I hope this cout is simple!
cout << scalar_product(veca,vecb) << endl;
}
If you are using an IDE then just compile and run. If you are using command-line on a Unix-based system with g++ compiler, this is what you will do (where Scalar.cpp is the file containing code):
g++ Scalar.cpp -o scalar
To run it simply type
./scalar
You should get 1.99 as the output of the above program.