質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

1532閲覧

std::accumulate

Y.R.T

総合スコア42

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/08/07 01:56

アームストロング数に関する説明です。
【説明】
Michael F. Armstrongにちなんだ*1アームストロング数はナルシシスト数、拡張完全
数(plus perfect number)、拡張完全桁不変数(pluperfect digital invariant)という呼び
名もありますが、ある数の桁数がnのとき、その数の各桁の数のn乗の総和が元の数と
等しい数です。例えば、3桁の最小のアームストロング数は153で13+53+33と等しく
なります。
3桁の数がアームストロング数かどうか調べるには、3乗して和を取る前にまず各桁
の数の値を求めなければなりません。そのためには、除算と剰余演算が必要になりま
すが、これよりも高速な方法があります。それは、10のべき乗を使って数を生成するも
のです。言い換えると、1000までの数をa10^2 + b10 + cと表します。3桁の数に限っ
ているので、aは1から始まります。除算や剰余演算より乗算のほうが速いので高速で
す。

【質問】
桁数に関わらず上限までのアームストロング数を求める構文の一部です。
構文内のstd::accumulateが4つの引数を持っていることで何をしているのかがわからず、
また、引数0の意味、s={return べき乗}の箇所が何をしようと知るのかがわかりません。

void print_narcissistics_3(int const limit, bool const printResults) { for (int i = 1; i <= limit; ++i) { std::vector<int> digits; int n = i; while (n > 0) { digits.push_back(n % 10); n = n / 10; } int arm = std::accumulate( std::begin(digits), std::end(digits), 0, [s = digits.size()](int const sum, int const digit) {return sum + static_cast<int>(std::pow(digit, s)); }); if (i == arm) { if (printResults) std::cout << arm << std::endl; } } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

構文内のstd::accumulateが4つの引数を持っていることで何をしているのかがわからず、

アルゴリズムstd::accumulateは、3引数版と4引数版の2種類がオーバーロード提供されます。

  • accumulate(InputIterator first, InputIterator last, T init);
  • accumulate(InputIterator first, InputIterator last, T init, BinaryOperation binary_op);

3引数版は累積操作として算術加算+を用いますが、4引数版は累積操作をカスタマイズできるよう拡張したものです。

c++

1// https://cpprefjp.github.io/reference/numeric/accumulate.html 引用 2template <class InputIterator, class T, class BinaryOperation> 3T accumulate(InputIterator first, InputIterator last, T init, 4 BinaryOperation binary_op) { 5 while (first != last) 6 init = binary_op(std::move(init), *first++); 7 return init; 8}

引数0の意味

std::accumulateの第3引数は、累積操作の初期値(init)を表します。
加算(+)の場合は初期値0を指定するのが一般的です。(加法単位元を指定)

s={return べき乗}の箇所が何をしようと知るのかがわかりません。

std::accumulateの第4引数に与えるカスタム累積操作として、ラムダ式 を定義しています。

c++

1// ラムダ式部分のみ引用 2[s = digits.size()] // ラムダ式内ローカ変数s へ digits.size() を代入 3(int const sum, int const digit) // ラムダ式は2つの引数をとり 4{ 5 return sum + static_cast<int>(std::pow(digit, s)); // sum + (digitのs乗) を返す 6}

投稿2020/08/07 02:51

yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Y.R.T

2020/08/07 03:59

ありがとうございます。 ラムダ式を思いだしました。 教えていただいた内容を把握中です。
guest

0

ベストアンサー

accumulate

C++

1// accumulate( first, last, init, f ) は以下と同等。 2{ 3 while ( first != last ) { 4 init = f(init, *first); 5 ++first; 6 } 7 return init; 8}

んでもって 上記 f のトコに
[s = digits.size()](int const sum, int const digit) {return sum + static_cast<int>(std::pow(digit, s)); }
が置かれてます。こいつは sum と digit を引数に受け取り sum + digit^s を返してますね。
(s : digits.size())

投稿2020/08/07 02:48

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Y.R.T

2020/08/07 03:57

大変わかりやすいです。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問