スポンサーリンク

可変長引数テンプレート関数で交換法則のない式を一気に計算する関数

例えばsumの場合、以下のように書ける。

転載元:http://yohshiy.blog.fc2.com/blog-entry-300.html

// 末端 isum
inline int isum()
{
  return 0;
}

// 再帰呼び出し isum
template<typename First, typename... Rest>
int isum(const First& first, const Rest&... rest)
{
  return first + isum(rest...);
}

+や*の場合は交換法則が成り立つ。つまり、

(a+(b+(c+d))) == (((a+b)+c)+d)

だ。しかし、例えば/の場合、交換法則が成り立たない

(a/(b/(c/d))) != (((a/b)/c)/d)

ではどうすればいいか。

// 再起の最後
template<typename First, typename Second>
inline auto div(const First& first, const Second& second)
{
  return first / second;
}

// 連続で割り算を行う関数
template<typename First, typename Second, typename... Rest>
inline auto div(const First& first, const Second& second, const Rest& ... rest)
{
  return div( div(first , second) , rest...);
}

動作確認

#include <iostream>

//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////

// 再起の最後
template<typename First, typename Second>
inline auto div(const First& first, const Second& second)
{
  return first / second;
}

// 連続で割り算を行う関数
template<typename First, typename Second, typename... Rest>
inline auto div(const First& first, const Second& second, const Rest& ... rest)
{
  return div(div(first, second), rest...);
}
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// 後ろから計算する場合

// 再起の最後
inline auto backDIV()
{
  return 1.0;
}

// 連続で割り算を行う関数
template<typename First, typename... Rest>
inline auto backDIV(const First& first, const Rest& ... rest)
{
  return first / backDIV(rest...) ;
}
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////


int main()
{
  std::cout << "普通計算:";
  double k1 = 5.0 / 8.0 / 2.0;
  std::cout << k1;

  std::cout << std::endl;
  std::cout << "再帰(前方):";
  double k2 = div(5.0, 8.0, 2.0);
  std::cout << k2;


  std::cout << std::endl;
  std::cout << "再帰(後方):";
  double k3 = backDIV(5.0, 8.0, 2.0);
  std::cout << k3;



  int i;
  std::cin >> i;
}

結果

普通計算:0.3125
再帰(前方):0.3125
再帰(後方):1.25

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: