Phorce
Phorce

Reputation: 4642

C++ Multiplying elements in a vector

I have been looking for a more optimal solution to the following and I cannot seem to find one.

Let's say I have a vector:

std::vector<double> vars = {1, 2, 3}

I want to perform 1 * 2 * 3 I know that I can do the following:

int multi = 1;

for(int i = 0; (i < vars.size()-1); i++)
{
    multi *= vars[i];
}

But, is there a more "C++11" way to do this? I really wanted to do this using lambda and so that I can calculate the multiply (product) of the vector without having another function inside the class, I'd rather have it calculated inside the function.

Upvotes: 25

Views: 41905

Answers (3)

Qaz
Qaz

Reputation: 61920

C++98

Yes, as usual, there is an algorithm (though this one's in <numeric>), std::accumulate (live example):

using std::begin;
using std::end;
double multi = std::accumulate(begin(vars), end(vars), 1.0, std::multiplies<double>());

std::multiplies is in <functional>, too. By default, std::accumulate uses std::plus, which adds two values given to operator(). std::multiplies multiplies them instead.

C++23

The C++23 ranges version of this function is std::ranges::fold_left. In addition, CTAD and improvements to the standard "operator objects" have made them nicer to use:

namespace rng = std::ranges;
auto multi = rng::fold_left(vars, 1.0, std::multiplies());

As a side note, C++17 also added std::reduce, which is permitted to do operations out of order for speed. There is currently no ranges version of this.

Upvotes: 56

Pavan Chandaka
Pavan Chandaka

Reputation: 12751

Another way is using inclusive_scan (C++17 and above)

The advantage is you can get multiplies of first "N" elements in a vector. Below is the code. Explanation in comments.

#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>

int main()
{
    //INPUT VECTOR
    std::vector<int> data{ 3, 1, 4, 1, 5, 9, 2, 6 };

    //OUTPUT VECTOR WITH MULTIPLIES
    //FIRST ELEMENT - 3 
    //SECOND ELEMENT - 3 * 1 
    //THIRD ELEMENT - 3 * 1 * 4 
    //FOURTH ELEMENT - 3 * 1 * 4 * 1
    // ..
    // ..
    //LAST ELEMENT - 3 * 1 * 4 * 1 * 5 * 9 * 2 * 6
    std::vector<int> multiplies(data.size());

    //Multiply all numbers in given vector.
    inclusive_scan(data.begin(), data.end(),
        multiplies.begin(),
        std::multiplies<>{});

    //PRODUCT OF FIRST 5 ELEMENTS.
    std::cout << "Product of first 5 elements :: " << multiplies[4] << std::endl;

    //PRODUCT OF ALL ELEMENTS
    std::cout << "Product of all elements :: " << multiplies[data.size() - 1] << std::endl;
}

Also there is an overload where the execution policy can be specified. Sequential execution or Parallel execution. Need to include "execution" header.

//MULTIPLY ALL NUMBERS IN VECTOR WITH PARALLEL EXECUTION.
inclusive_scan(std::execution::par,data.begin(), data.end(),
    multiplies.begin(),
    std::multiplies<>{});

Upvotes: 0

NathanOliver
NathanOliver

Reputation: 180630

You can use a ranged based for loop like:

std::vector<double> vars = {1, 2, 3}
int multi = 1;

for (const auto& e: vars)
    multi *= e;

Upvotes: 7

Related Questions