「竹内関数」の版間の差分
37行目: | 37行目: | ||
* [[遅延評価]] |
* [[遅延評価]] |
||
[[クロージャ]]などを利用して、関数呼び出しの計算より前に引数を計算すること([[先行評価]])をしない(ただし、クロージャ生成のコストがかかる)。原則として遅延評価する言語である[[Haskell]]では定義そのままで非常に速い。他にも[[Scala]]など遅延評価に対応した言語においては、簡単に、非常に高速に評価が終わるコードを作成できる。 |
[[クロージャ]]などを利用して、関数呼び出しの計算より前に引数を計算すること([[先行評価]])をしない(ただし、クロージャ生成のコストがかかる)。原則として遅延評価する言語である[[Haskell]]では定義そのままで非常に速い。他にも[[Scala]]など遅延評価に対応した言語においては、簡単に、非常に高速に評価が終わるコードを作成できる。 |
||
マッカーシー版は、メモ化では同様に速い。しかし、マッカーシー版をHaskellなどでそのままの定義で遅延評価した場合は、高速にならない(遅延評価では計算量が減らない)、という違いがある。 |
|||
== 参照 == |
== 参照 == |
2010年8月26日 (木) 03:46時点における版
竹内関数(たけうちかんすう)とは三つの整数 x, y, z に対して、次のように再帰的に定義される関数である。
定義からわかるように処理を次々にたらいまわしにしていくことから、たらいまわし関数、たらい関数(Tarai function)とも呼ばれる(後述のマッカーシー版との混同を避けるためこの名で呼ばれることのほうが多いが、こちらの定義のほうがオリジナルである。マッカーシー版を特にTak関数として区別する場合もある)。電電公社研究員(当時)の竹内郁雄が1976年に考案した。与える数によって関数の再帰呼び出しの回数が非常に増え、計算量が大きくなるため、コンピュータの性能測定などに用いられる。
マッカーシー版
ジョン・マッカーシーは竹内関数を記憶違いで[1] z を返すように変更し、これがTak関数として広まった。以下がその定義である。
計算量はずっと少ない。
本質
竹内関数の出力は以下のものと同等である。
ドナルド・クヌースによる研究が、Textbook Examples of Recursion(1990)にある。
高速化
竹内関数を高速化するには、関数呼び出しのコストを小さくする、というまっとうな手法と、計算を必要になるまでやらない(引数のx, y, zの値が実際に必要なのは、関数の呼び出し時でなくifの評価時で、しかも常に全部は必要としない)か、一度やった計算の結果を再利用するかして、計算量自体を削減する(当然非常に速い。ベンチマークとしては一種のチートと言えなくもない)手法とがあり、後者には次のような手法がある。
一度計算した値を覚えておき、次の呼び出しではその値を使う。
クロージャなどを利用して、関数呼び出しの計算より前に引数を計算すること(先行評価)をしない(ただし、クロージャ生成のコストがかかる)。原則として遅延評価する言語であるHaskellでは定義そのままで非常に速い。他にもScalaなど遅延評価に対応した言語においては、簡単に、非常に高速に評価が終わるコードを作成できる。
マッカーシー版は、メモ化では同様に速い。しかし、マッカーシー版をHaskellなどでそのままの定義で遅延評価した場合は、高速にならない(遅延評価では計算量が減らない)、という違いがある。
参照
関連項目
外部リンク
- TAK Function
- Wolfram MathWorld
- どう転んでもLisp - スライド10〜13に作者自身の解説がある
- 東京大学 竹内郁雄研究室