Skip to Content
Course content

205: The <numeric> Header: accumulate, inner_product

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Can I use accumulate for things other than just summing numbers?

Absolutely. While the name suggests a simple sum, std::accumulate is actually a general-purpose "fold" operation. It takes a range, an initial value, and an optional binary operation. If you don't provide that third argument, it defaults to addition, but you can pass in any function or lambda that knows how to combine two values.

I often use this when I need to collapse a collection into a single result that isn't a sum. For example, let's say you're building a simple string parser and you want to join a vector of strings into one comma-separated sentence. Instead of writing a for loop and manually managing the trailing comma, you can use a lambda:

#include <iostream>
#include <vector>
#include <numeric>
#include <string>

int main() {
    std::vector<std::string> words = {"C++", "is", "surprisingly", "powerful"};
    
    std::string sentence = std::accumulate(
        words.begin(), 
        words.end(), 
        std::string{}, // Initial value
        [](const std::string& a, const std::string& b) {
            return a.empty() ? b : a + " " + b;
        }
    );

    std::cout < sentence < "\n"; // "C++ is surprisingly powerful"
    return 0;
}

Why do I have to provide an initial value, and why does it sometimes break my math?

The initial value (the third argument) serves two purposes: it's the starting point for the accumulation, and—more importantly—it defines the return type of the function.

This is a classic trap I've seen juniors fall into. If you have a vector of doubles but you pass 0 (which is an int) as your starting value, std::accumulate will perform all the additions using integer math, truncating every single step. You'll end up with a whole number when you expected a decimal.

Always make sure your initial value matches the precision you need. Use 0.0 for doubles or 0LL for long longs. It seems like a tiny detail, but it's the kind of bug that can haunt a production codebase for weeks.

When should I use inner_product instead of just writing a loop?

You use std::inner_product when you have two sequences and you want to perform a "multiply-then-sum" operation. In mathematics, this is the dot product. In the real world, it's exactly how you calculate things like a weighted average or the total cost of an order.

Imagine you have one vector for the prices of items in a shopping cart and another vector for the quantities of those items. You could write a loop to multiply price[i] * quantity[i] and add it to a running total, but inner_product does this in one clean line. It's more expressive; when another engineer sees inner_product, they immediately know you're calculating a combined scalar value from two sets of data.

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

int main() {
    std::vector<double> prices = {19.99, 5.50, 12.00};
    std::vector<int> quantities = {1, 3, 2};

    // Multiply elements pairwise and sum them up, starting from 0.0
    double total_cost = std::inner_product(
        prices.begin(), prices.end(), 
        quantities.begin(), 
        0.0
    );

    std::cout < "Total Order Value: $" < total_cost < "\n";
    return 0;
}



📋 Practical Task

Exercise: Calculating a Weighted Grade Point Average

You are writing a module for a student portal. You need to calculate a student's final grade based on a weighted system where different assignments have different "weights" (impact on the final grade).

Your Task:

  • Create a std::vector<double> containing the student's scores (e.g., {85.0, 92.0, 78.0, 95.0}).
  • Create a std::vector<double> containing the corresponding weights for those scores (e.g., {0.1, 0.2, 0.3, 0.4}). Ensure the weights sum up to 1.0.
  • Use std::inner_product from the <numeric> header to calculate the final weighted average.
  • Print the final result to the console.

Bonus: Use std::accumulate to verify that your weights actually sum to 1.0 before performing the inner product calculation.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.