C/C++ Arena

Step 5 of 6

Review: integer math

Numeric code gets reviewed for four things: overflow, division by zero, signed/unsigned mix-ups, and empty input. None of them shows up with small, friendly test values, which is exactly why reviewers try unfriendly ones.

The four checks

#include <cstdint>
#include <iostream>
#include <vector>

// Percentage of bytes used, rounded down; 0 for a zero-size disk.
int percent_used(std::int64_t used, std::int64_t total) {
    if (total == 0) return 0;                            // division by zero
    return static_cast<int>(used * 100 / total);         // 64-bit math: no overflow
}

// Sum of the first n readings (all of them if fewer).
long long first_n(const std::vector<int>& r, std::size_t n) {
    long long sum = 0;                                   // wide accumulator
    for (std::size_t i = 0; i < n && i < r.size(); i++) sum += r[i];
    return sum;
}

int main() {
    std::cout << percent_used(3'000'000'000LL, 4'000'000'000LL) << "\n";
    std::cout << percent_used(0, 0) << "\n";
    std::cout << first_n({2'000'000'000, 2'000'000'000}, 5) << "\n";
    std::cout << first_n({}, 3) << "\n";
}
75
0
4000000000
0

Every line handles one of the four checks: the zero guard, 64-bit multiplication, a long long sum that can hold two billion plus two billion, and a loop bound that respects both n and the real size.

Where the conversion goes

static_cast<long long>(a) * 100 widens before multiplying. static_cast<long long>(a * 100) multiplies in int first, overflows, and only then widens the already wrong value. The same applies to sums: the accumulator's type must be wide from the start.

Your turn: this pull request adds stats for the match history page. The specification:

There are four bugs.

Previous: Review: modifying while iterating Next: Review: class design