Skip to Content
Course content

71: Algorithms Library: accumulate and count_if

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

I want to show you a snippet of code that looks perfectly fine at first glance, but it produces a result that will make you pull your hair out if you don't know how std::accumulate actually works under the hood. Imagine you're writing a small module to calculate the total cost of items in a digital shopping cart.

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

int main() {
    std::vector<double> prices = {10.99, 5.50, 20.25, 3.75};
    
    // We want the total sum of prices
    double total = std::accumulate(prices.begin(), prices.end(), 0);
    
    std::cout < "Total: " < total < std::endl; 
    return 0;
}

If you run this, you'll expect to see 40.49. Instead, you get 40. The decimals are just... gone. You might check your std::cout settings or double-check the vector values, but the logic seems airtight. So, what's happening?

The Integer Truncation Trap

The culprit is the third argument in std::accumulate: the initial value. In the code above, I passed 0. In C++, 0 is an int.

Here is the subtle part: std::accumulate uses the type of that initial value to determine the type of the internal accumulator. Because I provided an int, the function performs all its additions using integer arithmetic. Every time it adds a double from the vector to the running total, that double is cast to an int, stripping away the fractional part before the addition even happens. By the time the result is assigned to the double total variable, the precision is already lost.

Matching the Initial Value Type

To fix this, you have to be explicit about the type you want for the accumulation. If you're working with doubles, your starting value must be a double.

// Fix: Change 0 to 0.0
double total = std::accumulate(prices.begin(), prices.end(), 0.0);

By passing 0.0, you tell the compiler to use a double for the summation. Now the precision is preserved, and you get the 40.49 you were expecting. It's a tiny detail, but it's one of those "C++ moments" that catches even experienced devs when they're moving quickly.

Counting with Predicates

Now, usually, when we're summing things up, we also need to know how many items met a specific condition. You could write a for loop with an if statement and a counter, but that's boilerplate we don't need. That's where std::count_if comes in.

Unlike accumulate, which reduces a range to a single value via addition (by default), count_if takes a "predicate"—a function or lambda that returns true or false—and returns the number of elements for which that predicate was true.

Let's say we want to find out how many items in our cart are "premium" items (costing more than $10.00):

#include <algorithm> // Required for count_if

// ... inside main ...
int premium_count = std::count_if(prices.begin(), prices.end(), [](double p) {
    return p > 10.00;
});

std::cout < "Premium items: " < premium_count < std::endl;

I prefer count_if over a manual loop because it communicates intent. When another engineer sees count_if, they immediately know you're filtering and counting, rather than having to parse the logic inside a loop body to figure out what your goal was.




📋 Practical Task

Server Response Time Analyzer

You are tasked with analyzing a list of server response times (in milliseconds). You need to write a program that processes a std::vector<double> of response times to determine the system's health.

Requirements:

  • Create a vector containing these values: {120.5, 450.2, 80.1, 1100.7, 300.3, 1500.2, 95.4}.
  • Use std::accumulate to calculate the total time spent on all requests. (Ensure you don't fall into the truncation trap!)
  • Use std::count_if to count how many requests were "slow"—defined as any response time greater than 500.0ms.
  • Calculate the average response time by dividing the total time by the number of elements in the vector.
  • Print the total time, the number of slow requests, and the average response time to the console.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.