Scala 3のMatch Typeでコンパイル時ラマヌジャンで円周率求める

"コンパイルラマヌジャン"

って言いたかっただけです、すみませんでした。

match typeで遊ぶシリーズです。 (そんなシリーズ続くのか不明)

女神が夢の中でそうしろって言ってました、たぶん。 *1

ラマヌジャンにいく前に、まず見た目わかりやすいけど収束遅い?ライプニッツの公式でやってみましょう

ja.wikipedia.org

gist.github.com

全く工夫しないで書いたら 3.141 までしか正しくなりませんでした。つらいですね。 もっと大幅に項を増やそうとしてもStackOverflowしました。

続いてラマヌジャン?です。 そもそも公式の形いっぱいあるとか、そのあたりの詳細は詳しくないので触れません。 これも一応ラマヌジャンでいいんですよね?

適当にググって出てきた中で、Scala 3標準のcompiletimeで用意されてる範囲で計算しやすそうなやつです。 (平方根あると辛い、など)

どれが収束有利とかは、あまり深く考えてません。

n = 0 ( ( 2 n ) ! ) 3 ( n ! ) 6 42 n + 5 2 12 n = 16 π

gist.github.com

5項までしか計算してないのに 3.14159265 まで正しいです、やった〜。

ちなみに6以降はDoubleかLongか何かがオーバーフローして計算不可能でした。

細かい誤差や効率考えずに標準のIntとLongとDoubleを愚直に使っただけなので、同じような種類の公式でも、工夫次第ではもっと精度良くすることが可能かもしれません。

Scala 3でのMatch Typeでのプログラミングは、制限がすごく強いので、色々とアルゴリズムを1から考える必要があって、頭の体操になって楽しいですよ(?)

発展的課題としては、どうにかしてDoubleの精度ギリギリまで全部計算するとか、コンパイル時に使える有理数やBigIntを1から作って、さらにDoubleの上を目指す、などしてみると楽しいでしょう(?)

*1:これきいて、こいつ何言ってるんだ???と思った人は、ラマヌジャンについてググろう