C++教科書/標準ライブラリ編/<numeric>の章

編集

概要

編集

<numeric> ヘッダーは、C++ 標準ライブラリの一部であり、数値計算のための関数群を提供します。これらの関数は、配列や範囲の要素に対する累積、部分和、隣接差分などの操作を効率的に行うことができます。また、gcdlcm などの整数演算や、midpointsaturate_cast などの汎用的な関数も提供します。

関数リファレンス

編集

累積

編集
accumulate
範囲の要素を累積的に合計します。
関数テンプレートであり、オプションで二項演算子を指定できます。
template <class InputIt, class T>
constexpr T accumulate(InputIt first, InputIt last, T init);

template <class InputIt, class T, class BinaryOperation>
constexpr T accumulate(InputIt first, InputIt last, T init,
                       BinaryOperation binary_op);
reduce
範囲の要素を順に処理し、最終的な値を返します。
関数テンプレートであり、オプションで二項演算子を指定できます。
並行実行にも対応しています。
template <class InputIt>
constexpr typename iterator_traits<InputIt>::value_type reduce(InputIt first,
                                                               InputIt last);

template <class InputIt, class T>
constexpr T reduce(InputIt first, InputIt last, T init);

template <class InputIt, class T, class BinaryOperation>
constexpr T reduce(InputIt first, InputIt last, T init,
                   BinaryOperation binary_op);

template <class ExecutionPolicy, class ForwardIt>
typename iterator_traits<ForwardIt>::value_type
reduce(ExecutionPolicy &&exec, ForwardIt first, ForwardIt last);

template <class ExecutionPolicy, class ForwardIt, class T>
T reduce(ExecutionPolicy &&exec, ForwardIt first, ForwardIt last, T init);

template <class ExecutionPolicy, class ForwardIt, class T,
          class BinaryOperation>
T reduce(ExecutionPolicy &&exec, ForwardIt first, ForwardIt last, T init,
         BinaryOperation binary_op);

内積

編集
inner_product
2つの範囲の要素の内積を計算します。
オプションで、二項演算子をそれぞれ要素と積に適用できます。
template <class InputIt1, class InputIt2, class T>
constexpr T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2,
                          T init);

template <class InputIt1, class InputIt2, class T, class BinaryOperation1,
          class BinaryOperation2>
constexpr T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2,
                          T init, BinaryOperation1 binary_op1,
                          BinaryOperation2 binary_op2);

変換・累積

編集
transform_reduce
範囲の要素を順に処理し、最終的な値を返します。
各要素を変換してから累積を行います。
オプションで、二項演算子と単項演算子を指定できます。
並行実行にも対応しています。
template <class InputIt1, class InputIt2, class T>
constexpr T transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2,
                             T init);

template <class InputIt1, class InputIt2, class T, class BinaryOperation1,
          class BinaryOperation2>
constexpr T transform_reduce(InputIt1 first1, InputIt1 last1, InputIt2 first2,
                             T init, BinaryOperation1 binary_op1,
                             BinaryOperation2 binary_op2);

template <class InputIt, class T, class BinaryOperation, class UnaryOperation>
constexpr T transform_reduce(InputIt first, InputIt last, T init,
                             BinaryOperation binary_op,
                             UnaryOperation unary_op);

template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T,
          class BinaryOperation1, class BinaryOperation2>
T transform_reduce(ExecutionPolicy &&exec, ForwardIt1 first1, ForwardIt1 last1,
                   ForwardIt2 first2, T init, BinaryOperation1 binary_op1,
                   BinaryOperation2 binary_op2);

template <class ExecutionPolicy, class ForwardIt, class T,
          class BinaryOperation, class UnaryOperation>
T transform_reduce(ExecutionPolicy &&exec, ForwardIt first, ForwardIt last,
                   T init, BinaryOperation binary_op, UnaryOperation unary_op);

部分和

編集
partial_sum
範囲の要素を順に累積し、その結果を別の範囲に格納します。
オプションで、二項演算子を指定できます。
template <class InputIt, class OutputIt>
constexpr OutputIt partial_sum(InputIt first, InputIt last, OutputIt result);

template <class InputIt, class OutputIt, class BinaryOperation>
constexpr OutputIt partial_sum(InputIt first, InputIt last, OutputIt result,
                               BinaryOperation binary_op);

排他スキャン

編集
exclusive_scan
範囲の要素を順に処理し、その累積を別の範囲に格納します。
各要素は、その前の要素までの累積には含まれません。
オプションで、二項演算子を指定できます。
並行実行にも対応しています。
template <class InputIt, class OutputIt, class T>
constexpr OutputIt exclusive_scan(InputIt first, InputIt last, OutputIt result,
                                  T init);

template <class InputIt, class OutputIt, class T, class BinaryOperation>
constexpr OutputIt exclusive_scan(InputIt first, InputIt last, OutputIt result,
                                  T init, BinaryOperation binary_op);

template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T>
ForwardIt2 exclusive_scan(ExecutionPolicy &&exec, ForwardIt1 first,
                          ForwardIt1 last, ForwardIt2 result, T init);

template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T,
          class BinaryOperation>
ForwardIt2 exclusive_scan(ExecutionPolicy &&exec, ForwardIt1 first,
                          ForwardIt1 last, ForwardIt2 result, T init,
                          BinaryOperation binary_op);

包含スキャン

編集
inclusive_scan
範囲の要素を順に処理し、その累積を別の範囲に格納します。
各要素は、その前の要素までの累積と自身の値を含みます。
オプションで、二項演算子を指定できます。
並行実行にも対応しています。
template <class InputIt, class OutputIt, class BinaryOperation,
          class UnaryOperation>
constexpr OutputIt
transform_inclusive_scan(InputIt first, InputIt last, OutputIt result,
                         BinaryOperation binary_op, UnaryOperation unary_op);

template <class InputIt, class OutputIt, class BinaryOperation,
          class UnaryOperation, class T>
constexpr OutputIt transform_inclusive_scan(InputIt first, InputIt last,
                                            OutputIt result,
                                            BinaryOperation binary_op,
                                            UnaryOperation unary_op, T init);

template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T,
          class BinaryOperation, class UnaryOperation>
ForwardIt2 transform_inclusive_scan(ExecutionPolicy &&exec, ForwardIt1 first,
                                    ForwardIt1 last, ForwardIt2 result,
                                    BinaryOperation binary_op,
                                    UnaryOperation unary_op);

template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2, class T,
          class BinaryOperation, class UnaryOperation>
ForwardIt2 transform_inclusive_scan(ExecutionPolicy &&exec, ForwardIt1 first,
                                    ForwardIt1 last, ForwardIt2 result,
                                    BinaryOperation binary_op,
                                    UnaryOperation unary_op, T init);

隣接差分

編集
adjacent_difference
範囲の隣接要素の差分を別の範囲に格納します。
オプションで、二項演算子を指定できます。
template <class InputIt, class OutputIt>
constexpr OutputIt adjacent_difference(InputIt first, InputIt last,
                                       OutputIt result);

template <class InputIt, class OutputIt, class BinaryOperation>
constexpr OutputIt adjacent_difference(InputIt first, InputIt last,
                                       OutputIt result,
                                       BinaryOperation binary_op);

template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2>
ForwardIt2 adjacent_difference(ExecutionPolicy &&exec, ForwardIt1 first,
                               ForwardIt1 last, ForwardIt2 result);

template <class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
          class BinaryOperation>
ForwardIt2 adjacent_difference(ExecutionPolicy &&exec, ForwardIt1 first,
                               ForwardIt1 last, ForwardIt2 result,
                               BinaryOperation binary_op);

イオタ

編集
iota
指定された値から順に増加する整数を範囲に格納します。
template <class ForwardIt, class T>
constexpr void iota(ForwardIt first, ForwardIt last, T value);

namespace ranges {
template <class O, class T> using iota_result = out_value_result<O, T>;

template <input_or_output_iterator O, sentinel_for<O> S, weakly_incrementable T>
  requires indirectly_writable<O, const T &>
constexpr iota_result<O, T> iota(O first, S last, T value);

template <weakly_incrementable T, output_range<const T &> R>
    constexpr iota_result <
    borrowed</ code> constexpr iota_result<borrowed_iterator_t<R>, T>
    iota(R &&r, T value);
} // namespace ranges

最大公約数

編集
gcd
2つの整数の最大公約数を計算します。
template<class M, class N>
constexpr common_type_t<M, N> gcd(M m, N n);

最小公倍数

編集
lcm
2つの整数の最小公倍数を計算します。
template<class M, class N>
constexpr common_type_t<M, N> lcm(M m, N n);

中点

編集
midpoint
2つの数値の中点を計算します。
template <class T> constexpr T midpoint(T a, T b) noexcept;

template <class T> constexpr T *midpoint(T *a, T *b);

飽和算術

編集
add_sat
2つの整数の加算を飽和演算で行います。
溢れが発生しないように、結果を範囲内に収めます。
template<class T>
constexpr T add_sat(T x, T y) noexcept;
sub_sat
2つの整数の減算を飽和演算で行います。
溢れが発生しないように、結果を範囲内に収めます。
template<class T>
constexpr T sub_sat(T x, T y) noexcept;
mul_sat
2つの整数の乗算を飽和演算で行います。
溢れが発生しないように、結果を範囲内に収めます。
template<class T>
constexpr T mul_sat(T x, T y) noexcept;
div_sat
2つの整数の除算を飽和演算で行います。
0除算や負の商が発生しないように、結果を範囲内に収めます。
template<class T>
constexpr T div_sat(T x, T y) noexcept;
saturate_cast
型変換を飽和演算で行います。
範囲外の値は、範囲内の値に変換されます。
template<class T, class U>
constexpr T saturate_cast(U x) noexcept;

C++11 以降の新機能

編集
C++11 では、以下の関数が追加されました。
iota
ranges::iota
C++20 では、以下の関数が追加されました。
midpoint
C++26 では、以下の関数が追加されました。
add_sat
sub_sat
mul_sat
div_sat
saturate_cast

応用例

編集

配列の要素の合計を求める

編集
#include <iostream>
#include <numeric>

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int sum = std::accumulate(numbers, std::end(numbers), 0);
    std::cout << "合計: " << sum << std::endl;
    return 0;
}

このコードは、numbers 配列の要素の合計を std::accumulate 関数を使用して計算します。

配列の隣接要素の差分を求める

編集
#include <iostream>
#include <numeric>

int main() {
    int numbers[] = {1, 2, 3, 4, 5};
    int sum = std::accumulate(numbers, std::end(numbers), 0);
    std::cout << "合計: " << sum << std::endl;
    return 0;
}

このコードは、numbers 配列の隣接要素の差分を std::adjacent_difference 関数を使用して計算します。