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.
Related
I have made a simple program that performs basic arithmetic operations on all the elements of a given array. But the problem is that the code is very repetitive and it's not a good practice to write repeated code and I can't come up with a solution to this problem.
How can we minimize code repetition in this program?
int add(int numcount, int numarr[]){
int total = numarr[0];
// add all the numbers in a array
for (int i = 1; i < numcount; i++){
total += numarr[i];
}
return total;
}
int sub(int numcount, int numarr[]) {
int total = numarr[0];
// subtract all the numbers in array
for (int i = 1; i < numcount; i++){
total -= numarr[i];
}
return total;
}
int mul(int numcount, int numarr[]) {
int total = numarr[0];
// multiply all the numbers in array
for (int i = 1; i < numcount; i++){
total *= numarr[i];
}
return total;
}
int main(int argc, char* argv[]){
const int n = 5;
int arr[n] = {1, 2, 3, 4, 5};
cout << "Addition: " << add(n, arr) << endl;
cout << "Subtraction: " << sub(n, arr) << endl;
cout << "Multiplication: " << mul(n, arr) << endl;
}
How can we minimize code repetition in this program?
Generically, by identifying the repeated structure and seeing whether we can either abstract it out, or find an existing name for it.
The repeated structure is just setting the running result to the first element of a container, and using a binary function to combine it with each subsequent element in turn.
Take a look at the Standard Algorithms library and see if any existing function looks similar
std::accumulate can do what we need, without any extra arguments for the add, and with just the appropriate operator function object for the others
So, you can trivially write
int add(int numcount, int numarr[]){
return std::accumulate(numarr, numarr+numcount, 0);
}
// OK, your sub isn't actually trivial
int sub(int numcount, int numarr[]){
return std::accumulate(numarr+1, numarr+numcount, numarr[0],
std::minus<int>{});
}
// could also be this - honestly it's a little hairy
// and making it behave well with an empty array
// requires an extra check. Yuck.
int sub2(int numcount, int numarr[]){
return numarr[0] - add(numcount-1, numarr+1);
}
etc.
It would be slightly nicer to switch to using std::array, or to use ranges if you're allowed C++20 (to abstract iterator pairs over all containers).
If you must use C arrays (and they're not decaying to a pointer on their way through another function), you could write
template <std::size_t N>
int add(int (&numarr)[N]){
return std::accumulate(numarr, numarr+N, 0);
}
to save a bit of boilerplate (passing numcount everywhere is just an opportunity to get it wrong).
NB. as mentioned in the linked docs, std::accumulate is an implementation of a left fold. So, if the standard library didn't provide accumulate, there's still an existing description of the "thing" (the particular "higher-order function") we're abstracting out of the original code, and you could write your own foldl template function taking the same std::plus, std::minus etc. operator functors.
You can use std::accumulate:
auto adder = [](auto accu,auto elem) { return accu + elem; };
auto multiplier = [](auto accu, auto elem) { return accu * elem; };
auto sum = std::accumulate(std::begin(arr),std::end(arr),0,adder);
auto prod = std::accumulate(std::begin(arr),std::end(arr),0,multiplier);
The result of sub is just 2*arr[0] - sum.
Be careful with the inital value for std::accumulate. It determines the return type and multiplying lots of int can easily overflow, perhaps use 0LL rather than 0.
In cases where std::accumulate nor any other standard algorithm fits, and you find yourself writing very similar functions that only differ by one particular operation, you can refactor to pass a functor to one function that lets the caller specifiy what operation to apply:
template <typename F>
void foo(F f) {
std::cout << f(42);
}
int identity(int x) { return x;}
int main() {
foo([](int x) { return x;});
foo(identity);
}
Here foo prints to the console the result of calling some callable with parameter 42. main calls it once with a lambda expression and once with a free function.
How can we minimize code repetition in this program?
One way to do this is to have a parameter of type char representing the operation that needs to be done as shown below:
//second parameter denotes the operator which can be +, - or *
int calc(int numcount, char oper, int numarr[])
{
//do check here that we don't go out of bounds
assert(numcount > 0);
int total = numarr[0];
// do the operatations for all the numbers in the array
for (int i = 1; i < numcount; i++){
total = (oper == '-') * (total - numarr[i]) +
(oper == '+') * (total + numarr[i]) +
(oper == '*') * (total * numarr[i]);
}
return total;
}
int main()
{
int arr[] = {1,2,3,4,5,6};
std::cout << calc(6, '+', arr) << std::endl; //prints 21
std::cout << calc(6, '-', arr) << std::endl; //prints -19
std::cout << calc(6, '*', arr) << std::endl; //prints 720
}
Working demo
I already know how to create a dynamic 2D matrix using new and free it using delete. Since C++ 11 is here with many new memory features such as unique_ptr, array container etc.; what is a nice way to create a 2D matrix so that one needs not to free the matrix explicitly using delete operator?
One of the simplest ways is to use a vector of vectors
const int N = 10;
const int M = 10;
vector<vector<int>> matrix2d(N, vector<int>(M, 0)); // 10x10 zero-initialized matrix
matrix2d[0][0] = 42;
You could of course use a single vector and wrap it into an accessor class
vector<int> matrix(N * M, 0) // Ditto as above, but needs stride-aware accessors
I'll post a small example here for completeness' sake
template <typename T>
class Matrix2D {
std::vector<T> data;
unsigned int sizeX, sizeY;
public:
Matrix2D (unsigned int x, unsigned int y)
: sizeX (x), sizeY (y) {
data.resize (sizeX*sizeY);
}
T& operator()(unsigned int x, unsigned int y) {
if (x >= sizeX || y>= sizeY)
throw std::out_of_range("OOB access"); // Throw something more appropriate
return data[sizeX*y + x]; // Stride-aware access
}
};
Live Example
or perhaps combine your way with a smart pointer. Notice that the vector<vector<int>> approach should be used with caution since the vectors are independent from each other and there's nothing to enforce that they should keep their size fixed.
I strongly suggest using array_view from the GSL, which will eventually be part of the standard.
#include <array>
#include <vector>
#include "array_view.h" // must be manually imported until standardization
int main()
{
std::array<int, 10> arr{}; // 10 ints on the stack
std::vector<int> vec{12}; // 12 ints on the heap
auto a = gsl::array_view<int, 2>{{2, 5}, arr}; // 2D, 2x5 matrix
auto b = gsl::array_view<int, 3>{{3, 2, 2}, vec}; // 3D, 3x2x2 matrix
auto c = gsl::array_view<int>{vec}; // 1D, spans from `begin()` to `end()`
a[{0,3}] += b[{0,1,1}] * -c[2]; // access syntax
}
N.B. array_view holds no control over the lifetime of the range it looks at. See here for full details.
Edit:
array_view is dead as it was becoming too complicated in handling multidimensional arrays with zero cost abstraction. You should instead use span from the GSL.
See this for more information about span.
Based on above answers, I have found a simple way to create matrices although not using C++11 features. Here is an illustration.
#include <iostream>
#include <vector>
using namespace std;
typedef vector<vector<int>> Matrix2D;
typedef vector<Matrix2D> Matrix3D;
Matrix2D my_arr;
int main()
{
const size_t N = 9;
for(unsigned s = 4; s <= N; s++)
{
my_arr.resize(s);
for(unsigned i = 0; i < s; i++)
my_arr[i].resize(s,s);
for(unsigned i = 0; i < s; i++)
{
for(unsigned j = 0; j < s; j++)
cout << my_arr[i][j] << " ";
cout << endl;
}
cout << "\n\n";
}
return 0;
}
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;
}
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've written a loop in C++ to give me 6 random numbers and store them in an array.
What I would like to do is to sum the elements of the array until I get a value larger than a number, "x", but I would like to do this without necessarily adding all the elements. The objective is to find the first elements which sum to the value of x.
For example, array is [1,2,3,4,5,6], and x = 6, so what I would be looking for are the elements [1,2,3].
I've looked at the standard library and have tried using the sum function from "valarray" but this just gives the sum of all the elements. Any ideas on how to code this successfully would be greatly appreciated.
Write a functor that does the addition.
#include <algorithm>
struct SumToo
{
SumToo(int val):m_val(val),m_sum(0) {}
int m_val;
int m_sum;
bool operator()(int next)
{
m_sum += next;
return m_sum >= m_val;
}
};
int main()
{
int data[] = {1,2,3,4,5,6};
int* find = std::find_if(data,data+6,SumToo(6));
}
I'm assuming you just want the first X elements in the array, up until their sum meets or exceeds a threshold (the question was a little vague there).
If so, I don't know how to do that without your own loop:
int sum = 0;
int i = 0;
for( ; i < len; ++i ) {
sum += array[i];
if( sum >= 6 ) {
break;
}
}
Now "i" contains the index at which the sum met or exceeded your threshold.
Avoid the answers that suggest using find_if with a stateful predicate. Stateful predicates are dangerous as the STL algorithms assume it is safe to copy predicates. In this case, if copies are made of the predicate then each will have a different 'running total' and will not necessarily act on all values, or in the correct order.
Especially avoid the solution that implements its predicate's operator() member as a const member function but labels its members as mutable as this is fooling you into thinking it is not a stateful predicate, which is bad.
I'd suggest using either one of the answers that simply loops to find the answer, or the answer that uses an accumulator, as that is the most correct way to do it (even if the code looks a little unwieldy.
Note that the warnings may well not apply to C arrays and find_if; I just don't want you to learn that stateful predicates are the right way to solve your problem since you may end up using that incorrect solution in a situation where it is dangerous in future.
Reference: C++ Coding Standards: 101 Rules, Guidelines, and Best Practices, Item 87
Here's a slightly more generic version:
#include <iostream>
#include <algorithm>
// return an iterator _Last such that sum
// of all elements in the range [_First, _Last)
// satisfies the predicate Func
template<class InIt,
class Ty,
class Fn> inline
InIt accumulate_if(InIt First, InIt Last, Ty Val, Fn Func)
{
for (; Func(Val) && First != Last; ++First)
Val = Val + *First;
return (First);
}
int main() {
int num[] = {1, 2, 3, 4, 5, 6};
int *last = accumulate_if(num, num + sizeof num / sizeof num[ 0 ],
0, std::bind2nd(std::less<int>(), 6));
std::copy(num, last, std::ostream_iterator<int>(std::cout, "\n"));
return 0;
}
Substract the numbers from x one by one, until you reach 0 or lower.
No additions, as you wished :)
Here's hoping this works:
/* Returns an index i, given array valarray[0,1..n] and number x where i is an index to valarry such that sum over j of valarray[j] for j = 0 to i > x */
int getFirstSum(int *valarray, int n, int x)
{
int i = 0;
int sum = x;
while(sum > x && i < n)
{
i++;
sum -= valarray[i];
}
return i;
}
would be something like:
struct StopAtValue{
StopAtValue(int sum) : m_sum(sum), m_accumulated(0){}
bool operator()(int val){
m_accumulated += val;
return m_accumulated >= sum;
}
int m_sum;
int m_accumulated;
}
int* pos = std::find_if(&array[0], &array[n], StopAtValue(6));
Well, i would use a vector
T addUntil(T array[],size_t len,T thres){
vector<T> vec = vector_from_array(array,len)
T sum;
for (size_t i=0;i< vec.size(),sum<thresh;i++){
sum+= vec[i];
}
return sum;
}
T would need operator+ and operator< to be defined.
You could use std::find_if() along with a functor that maintains a running total, and only returtn true from the functor when you have found the element that puts you at or over the top.
For example:
#include <cstdlib>
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
using namespace std;
// functor returns true when the running total >= findVal
struct running_total : public unary_function<int, bool>
{
running_total(int findVal) : findVal_(findVal), runningTtl_(0) {};
bool operator()(int rhs) const
{
runningTtl_ += rhs;
if( runningTtl_ >= findVal_ )
return true;
else
return false;
}
private:
mutable int runningTtl_;
const int findVal_;
};
int main()
{
int nums[] = {1, 2, 3, 4, 5, 6};
size_t count = sizeof(nums)/sizeof(nums[0]);
const int scanTtl = 6; // running total to scan to
int * pos = find_if(&nums[0], &nums[0]+count, running_total(scanTtl));
cout << "Elements Totaling " << scanTtl << " : ";
copy(&nums[0], pos+1, ostream_iterator<int>(cout, ", "));
return 0;
}