パイを見つける5秒


11

パイ倍の電子 100の小数点以下の桁数に(またはパイあなたの曖昧な表記のような場合)は、次のとおりです。

8.5397342226735670654635508695465744950348885357651149618796011301792286111573308075725638697104739439...

OIES A019609)(非合理性の可能性に関する議論

あなたの仕事は、正の整数Nを取り、小数点以下N桁に切り捨てられたPi * eを出力するプログラムを書くことです。たとえば、N = 2の場合、出力はである必要があります8.53

これは最適化の問題であるため、最高値のNに対して正しい出力を提供できるサブミッションが勝ちます。

すべての提出物が同じコンピューティングパワーを使用して判断されるようにするに、コードがサポートする言語を使用してideone実行する必要がありますideone faqによると、ログインしていないユーザーには5秒の実行時間制限があります。この5秒の制限は、ログインするユーザーの15秒の制限ではなく、使用する必要がある制限です。(メモリ、コードサイズなどの他の制限については、よくある質問をご覧ください)

具体的には、ideoneにログインしていない人は、1から最大NmaxまでのNのすべての値に対してideoneでプログラムを実行でき、ほぼ常に正しい出力を確認できます。どのなしTime limit exceededMemory limit exceeded、などのエラー。Nmaxが最大の提出が勝ちです。

(実際にかかった時間が5秒を超えるかどうかは、イデオンがエラーを出さない限り重要ではありません。「ほぼすべての時間」は、特定のNの95%以上の時間として定義されます。)

詳細

  • 任意の数学的な方法を使用してPi * eを計算できますが、Pi、eまたはPi * eの最初の12桁を超えて出力をハードコーディングすることはできません
    • リソースは無制限であれば、プログラムは任意のNで機能する必要があります。
    • あなたの言語がたまたま持っている場合は、組み込みのPiまたはe定数を使用できます。
  • コードの外部のWebサイトやリソースにアクセスすることはできません(これが許可されている場合)。
  • ハードコーディングと外部リソースへのアクセスを超えて、ideoneが許可するものはほぼ間違いなく問題ありません。
  • 入力と出力は、(明らかに)ideoneがI / Oに提供するもの(stdin / stdoutのみ)で動作する必要があります。入力Nを引用符で囲む必要がある場合や、出力がans = ...などの場合は問題ありません。
  • Nmaxを入力として、コードのideoneスニペットへのリンクを含めてください。
  • 同点が発生した場合(複数の送信が64kBの出力文字制限に達した場合のみ)、最高票の回答が勝ちます。

3
うーん...あいまいなパイ。
デニス14

これは非常に簡単にコードゴルフになる可能性があり、もしそうならもっと楽しいでしょう。
オプティマイザー14

2
@Optimizerそれはコードゴルフかもしれませんが、そうすれば、それは他のすべての数字生成コードゴルフとほとんど同じでしょう。オンラインで確認できる時間ベースのコンテストを試してみたかった。(より複雑な計算上の問題の方がよかったかもしれませんが)
カルビンの趣味14

これがコードの場合、ゴルフAPLが勝つ可能性があります(任意の精度部分を
除く

1
これらのプログラムは、数字をstdoutに書き込もうとして完全にIOバウンドになると思われます。y-cruncherなどの場合、5秒は長い時間です。
ウィル

回答:


12

Python-65535

http://ideone.com/knKRhn

from math import exp, log

def divnr(p, q):
  """
    Integer division p/q using Newton-Raphson Division.
    Assumes p > q > 0.
  """

  sp = p.bit_length()-1
  sq = q.bit_length()-1
  sr = sp - sq + 1

  s = []
  t = sr
  while t > 15:
    s = [t] + s
    t = (t>>1) + 1
  # Base-case division
  r = (1 << (t<<1)) / (q >> sq-t)

  for u in s:
    r = (r << u-t+1) - (r*r * (q >> sq-u) >> (t<<1))
    t = u
  return (r * (p >> sq)) >> sr

def pibs(a, b):
  if a == b:
    if a == 0:
      return (1, 1, 1123)
    p = a*(a*(32*a-48)+22)-3
    q = a*a*a*24893568
    t = 21460*a+1123
    return (p, -q, p*t)
  m = (a+b) >> 1
  p1, q1, t1 = pibs(a, m)
  p2, q2, t2 = pibs(m+1, b)
  return (p1*p2, q1*q2, q2*t1 + p1*t2)

def ebs(a, b):
  if a == b:
    if a == 0:
      return (1, 1)
    return (1, a)
  m = (a+b) >> 1
  p1, q1 = ebs(a, m)
  p2, q2 = ebs(m+1, b)
  return (p1*q2+p2, q1*q2)

if __name__ == '__main__':
  n = input()

  pi_terms = int(n*0.16975227728583067)

  # 10^n == e^p
  p = n*2.3025850929940457

  # Lambert W_0(p/e) a la Newton
  k = log(p) - 1
  w = k - (k-1)/(k+1)
  while k > w:
    k = w
    w -= (k - p*exp(-k-1))/(k+1)

  # InverseGamma(e^p) approximation
  e_terms = int(p / w)

  pp, pq, pt = pibs(0, pi_terms)
  ep, eq = ebs(0, e_terms)

  z = 10**n
  p = 3528*z*ep*abs(pq)
  q = eq*abs(pt)

  pie = divnr(p, q)
  print pie,

Ideoneがgmpy2インストールされていないようです。これは少なくとも2つの理由で残念です。1つは、計算がはるかに高速になるためです。2つは、任意の精度の平方根を必要とする数式が実用的でなくなるためです。

πに使用する式は、ラマヌジャンによって式(39)としてリストされました

これは、用語ごとに〜5.89桁のレートで収束します。私の知る限り、これは、任意の精度の平方根の評価を必要としない、この種の最速の収束シリーズです。同じ論文のフォーミュラ(44)(用語ごとに収束率〜7.98桁)は、ほとんどの場合ラマヌジャンフォーミュラと呼ばれます。

eに使用する式は、逆階乗の合計です。mathoverflowで見つけた近似を使用して、必要な項の数はΓ -110 n)として計算されます。Lambert W 0コンポーネントは、ニュートン法を使用して検出されます。

これらの各合計の計算は、元は唐つばが考案した高速E関数評価(より一般的にはバイナリ分割として知られています)を介して行われます。この方法は、合計をn項に減らして単一の有理値p / qにします。これらの2つの値は、最終結果を生成するために乗算されます。

更新:
プロファイリングにより、計算に必要な時間の半分以上が最終部門に費やされたことが明らかになりました。qの最上位のlog 2(10 nビットのみが完全な精度を得るために必要なので、事前にいくつかを削除します。コードは3.33秒で Ideone出力バッファを満たします。

更新2:
これは課題であるため、CPythonの遅延に対処するために独自の除算ルーチンを作成することにしました。上記の実装でdivnrは、Newton-Raphson Divisionを使用します。一般的な考え方は、ニュートン法を使用してd = 1 / q・2 nを計算することです。ここで、nは結果に必要なビット数であり、結果をp・d >> nとして計算します。ランタイムは2.87秒になり、計算前にビットを切り落とすことさえありません。この方法では不要です。


4

パリ/ GP:33000

これは基本的にOEISで提供されるプログラムで、入力を受け取り、出力を正しくフォーマットするように修正されています。それは、他に何もないとしても、勝つためのベースラインとして役立つはずです。

これは正確だ思います。私はOEISに対して100および20kでチェックし、両方に一致しました。確認するためにオンラインでさらに数字を見つけるのは非常に困難です。

33,000の場合、約4.5秒かかりますので、おそらくわずかにぶつかります。入力とideoneの遅い送信/コンパイル/実行ループをいじるのにうんざりしました。

{ 
    m=eval(input());
    default(realprecision, m+80); 
    x=Pi*exp(1);
    s="8.";
    d=floor(x);
    x=(x-d)*10;
    for (n=1, m, d=floor(x); 
         x=(x-d)*10; 
         s=Str(s,d));
    print(s);
}

Ideone.comリンク


あなたの数字は私のものと一致するので、私は四肢に出て、おそらく正しいと言います。
primo 14

このプログラムは、本質的にすべての時間をループに費やし、数字を1つずつ生成します。あなたがちょうどStr(floor(frac(x)*10^m)それを取るなら、それは何百/何千倍も速く行きます。
チャールズ

2

Python 3

組み込みのpiとeには十分な桁がないため、自分で計算することにしました。

import decimal
import math
decimal.getcontext().prec=1000000
decimal=decimal.Decimal;b=2500
print(str(sum([decimal(1/math.factorial(x)) for x in range(b)])*sum([decimal(1/16**i*(4/(8*i+1)-2/(8*i+4)-1/(8*i+5)-1/(8*i+6))) for i in range(b)]))[0:int(input())+2])

IDEOneリンク

STDIN = 1000の出力:

8.5397342226735669504281233688422467204743749305568824722710929852470173635361001388261308713809518841081669216573834376992066672804294594807026609638293539437286935503772101801433821053915371716284188665787967232464763808892618434263301810056154560438283877633957941572944822034479453916753507796910068912594560500836608215235605783723340714760960119319145912948480279651779184356994356172418603464628747082162475871780202868607325544781551065680583616058471475977367814338295574582450942453416002008665325253385672668994300796223139976640645190237481531851902147391807396201201799703915343423499008135819239684881566321559967077443367982975103648727755579256820566722752546407521965713336095320920822985129589997143740696972018563360331663471959214120971348584257396673542429063767170337770469161945592685537660073097456725716654388703941509676413429681372333615691533682226329180996924321063261666235129175134250645330301407536588271020457172050227357541822742441070313522061438812060477519238440079

Nmaxは、ideoneが実行しなくなる前にプログラムに与えることができる最大の入力値です。
カルビンの趣味14

1
私はNmaxは任意の大きかかわらだと思うCalvin'sHobbies ... @
ベータ崩壊

1
ideoneは無限の計算能力をあなたに与えません。最大入力値は何であるあなたのプログラムがideone上で実行することができますか?(実際、プログラムはshould be able to work for any N, given unlimited resourcesルールに従っていません。出力のほとんどはN = 10000付近でゼロです。)
カルビンの趣味14

それはpython3ではありません:NameError: name 'xrange' not defined
バクリウ14

2

スカラ-1790

でIDEOne http://ideone.com/A2CIto

Wetherfieldの式をπに使用します(ここから粗に移植されたMachinの式コード)。通常のべき級数を使用してeを計算します。

object Main extends App {
  import java.math.{BigDecimal => JDecimal}
  import java.math.RoundingMode._
  import scala.concurrent.Future
  import scala.concurrent.Await
  import scala.concurrent.ExecutionContext.Implicits._
  import scala.concurrent.duration._
  val precision = 1800

  def acotPrecision(numDigits: Int)(x: BigDecimal) = {
    val x1 = x.underlying
    val two = JDecimal.valueOf(2)
    val xSquared = x1 pow 2
    val unity = JDecimal.ONE.setScale(numDigits, HALF_EVEN)
    var sum = unity.divide(x1, HALF_EVEN)
    var xpower = new JDecimal(sum.toString)
    var term = unity

    var add = false

    var n = JDecimal.valueOf(3).setScale(numDigits)
    while (term.setScale(numDigits, HALF_EVEN).compareTo(JDecimal.ZERO) != 0) {
      xpower = xpower.divide(xSquared, HALF_EVEN)
      term = xpower.divide(n, HALF_EVEN)
      sum = if (add) sum add term else sum subtract term
      add = !add
      n = n add two
    }
    sum
  }

  def ePrecision(numDigits: Int) = {
    val zero = JDecimal.ZERO
    var sum = zero
    var term = JDecimal.ONE.setScale(numDigits, HALF_EVEN)
    var n = JDecimal.ONE.setScale(numDigits, HALF_EVEN)
    while(term.setScale(numDigits, HALF_EVEN).compareTo(zero) != 0) {
      sum = sum add term
      term = term.divide(n, HALF_EVEN)
      n = n add JDecimal.ONE
    }
    sum
  }

  val acot = acotPrecision(precision) _

  def d(x: Int) = JDecimal.valueOf(x)

  def piFuture = Future(d(4) multiply (
    (d(83) multiply acot(107)) add (d(17) multiply acot(1710)) subtract (d(22) multiply acot(103697))
    subtract (d(24) multiply acot(2513489)) subtract (d(44) multiply acot(18280007883L))
   add (d(12) multiply acot(7939642926390344818L))
   add (d(22) multiply acot(BigDecimal("3054211727257704725384731479018")))
  ))

  def eFuture = Future(ePrecision(precision))

  Await.result(
    for (pi <- piFuture;
         e <- eFuture) yield println((pi multiply e).setScale(precision - 10, DOWN))
  , 5 seconds) 
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.