How to multiply and add corresponding elements in a vector

I have two vectors with elements

[10,20,30] and

[40,50,60]

I need the output as 10*40 + 20*50 + 30*60 = 3200

I wrote the following code but not getting the correct output. Can someone help me.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <vector>

using namespace std;

int main()
{
	vector<int> vect1{ 10, 20, 30 };
	vector<int> vect2{ 40, 50, 60 };

	int p = vect1.size();
	int total;

	for (int i = 0; i < p; i++)
	{
		total = vect1[i] * vect2[i];
	}
	cout << total << endl;
}
Last edited on
Initialize total to 0 int total = 0; and do total += vect1[i] * vect2[i];

PS: You weren't doing this because you assigned it before using it, but using the value of an uninitialized variable is undefined behavior. It will most likely cause that value to give a junk result. You can't assume that an uninitialized variable is 0.
Last edited on
Heh heh heh...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <functional>
#include <numeric>
#include <vector>

int main()
{
  std::vector<int> v1{ 10, 20, 30 };
  std::vector<int> v2{ 40, 50, 60 };

  int total = std::transform_reduce(
    v1.begin(), v1.end(), v2.begin(), 0,
    std::plus<int>(),
    std::multiplies<int>()
  );

  std::cout << total << "\n";
}

C++17 has some good stuff...
There's been std::inner_product since C++98

int total = std::inner_product(v1.begin(), v1.end(), v2.begin(), 0);

BTW, to represent a mathematical vector (e.g., 3 or 4-dimensional points), std::vector is probably not the best choice.
Last edited on
Doh!

And I knew about that one...
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <valarray>
using namespace std;

int main()
{
   valarray<int> vect1{ 10, 20, 30 };
   valarray<int> vect2{ 40, 50, 60 };
   cout << ( vect1 * vect2 ).sum() << '\n';
}
1
2
3
4
5
  int total = std::transform_reduce(
    v1.begin(), v1.end(), v2.begin(), 0,
    std::plus<int>(),
    std::multiplies<int>()
  );

In my opinion this is less readable than what OP had. It's nifty and all, and works with any conforming container, I just don't really see the advantage from a readability/maintainability standpoint.
Last edited on
In my opinion this is less readable than what OP had. It's nifty and all, and works with any conforming container, I just don't really see the advantage from a readability/maintainability standpoint.

Well, transform_reduce is parallelized, and the reduction is done in unspecified order (like std::reduce vs std::accumulate), so it's not exactly the same.

While we're on this topic, it might be worthwhile to write some wrappers for frequently used algorithms. That might mean writing range algorithms to avoid saying begin()/end() (until C++20), or versions that gives a default-initialized init to transform_reduce.

It's much nicer to say
1
2
my::transform_reduce(v1, v2, plus_fn, multiplies_fn); // better
my::dot_product(v1, v2); // even better 

It's generally easy to do this, and the payoff can be significant. Saves parsing a loop, even if it's really easy.

transform_reduce has a (IMO) more-useful single-range version. e.g., to compute the sum of a particular attribute:

1
2
3
inline constexpr auto plus_fn  = std::plus<>{};
inline constexpr auto get_x_fn = [](auto const& elt) { return elt.x; };
std::transform_reduce(std::begin(v), std::end(v), 0, plus_fn, get_x_fn);


P.S. regarding std::plus<int>{} and friends:
The feature proposal for C++14's transparent operator functors discusses why std::plus<void> is generally the best choice:
https://wg21.link/n3421

In general, prefer not to specify template arguments - let them be deduced instead. Getting a type slightly wrong can cause logic errors.
Last edited on
Personally, I use the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <duthomhas/for>
#include <iostream>
#include <vector>

int main()
{
  std::vector <int> xs{ 10, 20, 30 };
  std::vector <int> ys{ 40, 50, 60 };
  int dot_product = 0;

  for (auto [x, y] : xs, ys)
    dot_product += x * y;

  std::cout << dot_product << "\n";
}

Supposedly C++2a is supposed to do something similarly cool, but I don’t know the details.

:O)
:O) Indeed. The C++2a is most likely going to provide a function object named zip() to replace that scary comma.
Commas are less scary than people are taught to believe.

And I wrote the comma so I don't have to look at dumb “zip” fluff — extra verbiage to make your code look... like the obvious?

 
  for (auto [x, y] : zip( xs, ys ))  // how is this more readable? 

Zip is stupid anyway.

 
  for (auto [x, y, z] : zip( xs, ys, zs ))  // foo, won't compile! 

Betcha the C++ Committee will totally miss that use case. Every extant zip I’ve seen, including the ‘good’ ones *ahem*boost*ahem* have the same limitation.

What if the ranges are unequal in length? Every extant zip implementation barfs.
My fancy comma doesn’t.

1
2
3
4
5
6
  std::string          cs = "ABCD";  // Hey, aren't there too many letters here?
  int                  xs[] = { 1, 2, 3 };
  std::vector <double> ds { .1, .2, .3 };
  
  for (auto [c, x, d] : cs, xs, ds)  // Let's find out:
    std::cout << c << "," << x << "," << d << "\n";

Prints:
A,1,0.1
B,2,0.2
C,3,0.3
Huh.

No failure. Seems it worked as intended.


I too have always read the dire warnings about messing with the comma operator, and seen contrived examples of abuse to demonstrate problems. But honestly, every time I have played with RLM it has been pretty clear that you would be hard-pressed to break correct code with it.

Sure, I suppose it could break some stupidly-written code somewhere where someone thought he was being cool by using a comma instead of just writing two statements or some other “don’t do that!” karma problem.

Tough beans on bad code.

In this case, SFINAE makes it only work over classes where begin() and end() work, and packs it into a tuple of zip_iterator_pairs. If you try to use it outside this context you’ll have to explicitly bracket it anyway, and the tuple type will not likely be compatible with whatever you’re trying to do wrong, so it is pretty obvious when you’re misusing it.


All that for less than 150 lines of liberally commented code... and most of that was the zip_iterator class boilerplate. Heck, I didn’t even have to torture any meta-templates to do it.

Pretty proud of myself for that one, I am.


Too bad the beautiful C++ trying to get out keeps getting saddled by C++++ holy language stuff. I can’t tell you how much time I wasted trying to use various zip() implementations before my brain popped and I just wrote my own. (That works.)

/end , zip rant

Let’s eat, grandpa!
:O]
Duthomhas wrote:
for (auto [x, y, z] : zip( xs, ys, zs )) // foo, won't compile!
says who?
1
2
  for (auto [x, y, z] : view::zip(xs, ys, zs))
    dot_product += x * y * z;
https://wandbox.org/permlink/CantoQTyStZ3PSZO
Last edited on
Ah, nice, there is one that does compile.

It’s even uglier, though...
Topic archived. No new replies allowed.