查找pi的第n个小数


33

已经有30个专门针对pi的挑战,但是没有一个挑战要求您找到第n个小数,因此...

挑战

对于0 <= n <= 10000显示范围内的任何整数,pi的第n个小数。

规则

  • 小数点后的每个数字 3.
  • 您的程序可能是功能,也可能是完整程序
  • 您必须以10为底输出结果
  • 您可以n从任何合适的输入方法(stdin,input(),函数参数等)获得,但不进行硬编码
  • 如果您选择的语言是本机语言,则可以使用基于1的索引
  • 你不必处理无效的输入(n == -1n == 'a'n == 1.5
  • 允许内置,如果它们支持至少 10k小数
  • 运行时无关紧要,因为这是最短的代码,而不是最快的代码
  • 这是,以字节为单位的最短代码获胜

测试用例

f(0)     == 1
f(1)     == 4 // for 1-indexed languages f(1) == 1
f(2)     == 1 // for 1-indexed languages f(2) == 4
f(3)     == 5
f(10)    == 8
f(100)   == 8
f(599)   == 2
f(760)   == 4
f(1000)  == 3
f(10000) == 5

作为参考,在这里是圆周率的前10万位。


内置的?例如str(pi())[n+2]
primo

6
IMO最接近的重复目标是计算pi的截断数字总和(超载参数,否则将仅对此挑战施加有限的差异),精确传输pi(添加索引并抑制某些打印)和Pi窗口加密
彼得·泰勒

3
@Suever当然!该规则只是指出10k是您的程序应能够处理的最小值
Bassdrop Cumberwubwubwub

4
我建议在测试用例中添加f(599),因为很容易弄错(您需要大约3位小数的精度)。
aditsu

2
同样,f(760)= 4(从序列4 999999 8 开始)也很容易错误舍入。
Anders Kaseorg '16

Answers:


22

05AB1E,3个字节

žs¤

讲解

žs   # push pi to N digits
  ¤  # get last digit

在线尝试

使用基于1的索引。
最多支持100k位数字。


Pi到n位数字不舍入?
busukxuan

7
@busukxuan否。它使用pi到100k位的预定义常量,并检索其中的N个。
Emigna '16

4
@Emigna非常方便。好的解决方案。
Suever

2
短而锋利的PCG处于最佳状态
Xylius

16

Python 2,66字节

n=input()+9
x=p=5L**7
while~-p:x=p/2*x/p+10**n;p-=2
print`x/5`[-9]

输入来自标准输入。


样品用量

$ echo 10 | python pi-nth.py
8

$ echo 100 | python pi-nth.py
8

$ echo 1000 | python pi-nth.py
3

$ echo 10000 | python pi-nth.py
5

请注意在算法中使用n ... 599的输出应为2,而不是1。另外,您可能希望指定使用的是
python2。– aditsu

@aditsu更新。确认所有n≤1000
primo

1
如果n将输入作为加9,则可以避免括号。
xnor

@xnor d'哦。谢谢;)
primo 2016年

2
此算法生成的前几个数字是“ 3.141596535897932…”,它在位置5和6之间缺少“ 2”。为什么?因为那是Python 2的``运算符开始L向字符串追加的时候。
Anders Kaseorg '16

11

Bash + coreutils,60个 49字节

echo "scale=10100;4*a(1)"|bc -l|tr -d '\\\n'|cut -c$(($1+2))

bc -l<<<"scale=$1+9;4*a(1)-3"|tr -dc 0-9|cut -c$1

Dennis改进。谢谢!

索引是基于一的。


11

Python 2,73 71 73字节

感谢@aditsu将我的分数提高了2个字节

最终,可以在2秒内完成的算法。

n=10**10010
a=p=2*n
i=1
while a:a=a*i/(2*i+1);p+=a;i+=1
lambda n:`p`[n+1]

伊迪恩!

pi = 4*arctan(1)arctan(1)使用其taylor系列进行计算时使用公式。


相当快。但是,1-indexing不是python固有的。最后我记得(很久以来我一直不活跃),共识是需要定义函数,例如f=lambda n:...
primo

2
这里几乎每个lambda都是匿名的(您可以在此站点中使用Python搜索答案)
Leaky Nun

相关元帖子。似乎是违反了规则1和3(中运行代码后,就没有办法捕捉功能参考;函数的定义将需要为每个输入(被打了出来(lambda n:`p`[n+1])(1)(lambda n:`p`[n+1])(2)...)。
普里莫

1
您不能直接运行代码。这类似于import预先放置语句,只是这会预先生成一些全局变量。
Leaky Nun

i=3 while a:a=i/2*a/i;p+=a;i+=2为4
普里莫

7

MATL,11个10字节

@Luis节省了1个字节

YPiEY$GH+)

该解决方案利用基于1的索引

在线尝试

所有测试用例

说明

YP  % Pre-defined literal for pi
iE  % Grab the input and multiply by 2 (to ensure we have enough digits to work with)
Y$  % Compute the first (iE) digits of pi and return as a string
G   % Grab the input again
H+  % Add 2 (to account for '3.') in the string
)   % And get the digit at that location
    % Implicitly display the result

@LuisMendo哦,是的,我想输出已经是字符串了。h!
Suever,2016年

@LuisMendo哦,我从未真正想到这一点。我总是YP在测试符号工具箱时使用
Suever,2016年

YP实际上被允许吗?问题是,如果它支持<=
10000

@Suever OP声明“最多”而不是“至少”。据我了解,这意味着禁止支持> 10k。
busukxuan

@Suever是的,我想是的,我忍不住这样做了。因此,我删除了Sage答案。
busukxuan

6

Mathematica 30字节

RealDigits[Pi,10,1,-#][[1,1]]&

f=%

f@0
f@1
f@2
f@3
f@10
f@100
f@599
f@760
f@1000
f@10000

1
4
1
5
8
8
2
4
3
5


5

贤者,32 25字节

lambda d:`n(pi,9^5)`[d+2]

我用这种语言的第一个答案。

n四舍五入pi到17775位。


1
您需要print通话,否则这是一个片段,仅在REPL中有效。
Mego

这适用于(理论上)任何输入:lambda d:`n(pi,digits=d+5)`[-4]
Mego

2
@Mego没有“ 99999”运行吗?
busukxuan '16

1
@Mego,但随后将有更长的“ 9”运行时间。我不确定加倍长度是否可以通用,但由于无限猴子定理,我认为甚至不能做到这一点:en.wikipedia.org/wiki/Infinite_monkey_theorem
busukxuan

1
@busukxuan如果将π的未计算数字建模为随机数,则肯定会期望任意长的9s(并且我们没有理由期望真实π有所不同,尽管我们尚未证明这一点),但是您只希望得到一个只要9s的位置以很小的概率消失(尽管如此,我们还没有证明真实的π不会表现出意外)。我们发现至少有9个9s的运行,我认为这足以破坏[-8]建议。
Anders Kaseorg 2016年


4

Mathematica,23 21字节

⌊10^# Pi⌋~Mod~10&

SageMath,24个字节

lambda n:int(10^n*pi)%10

@LLlAMnYP我试过了,但是Mathematica似乎需要在Pi和之间(或之间#以及如果乘法被翻转)之间有一个空格,因此保存消失了。
Anders Kaseorg '16

实际上,它可以在Mathematica Online中使用(我一直在使用控制台版本),所以我想使用它。
Anders Kaseorg '16

4
这些应该是单独的答案。尽管它们使用相同的策略,但它们距离相同的语言并不遥远。
Mego

@Mego 我发现的策略没有说不同语言的答案不能算作非常相似。(答案表明未接受。)您是在指其他政策还是仅是偏好?
Anders Kaseorg '16

3

J19 15字节

10([|<.@o.@^)>:

取整数n并输出pi的 n 数字。使用基于零的索引。要获得第n 数字,请计算pi乘以10 n +1,取该值的下限,然后取模10。

用法

输入是扩展整数。

   f =: 10([|<.@o.@^)>:
   (,.f"0) x: 0 1 2 3 10 100 599 760 1000
   0 1
   1 4
   2 1
   3 5
  10 8
 100 8
 599 2
 760 4
1000 3
   timex 'r =: f 10000x'
1100.73
   r
5

在我的机器上,计算第10000 数字大约需要18分钟。

说明

10([|<.@o.@^)>:  Input: n
             >:  Increment n
10               The constant n
           ^     Compute 10^(n+1)
        o.@      Multiply by pi
     <.@         Floor it
   [             Get 10
    |            Take the floor modulo 10 and return

3

Clojure,312个字节

(fn[n](let[b bigdec d #(.divide(b %)%2(+ n 4)BigDecimal/ROUND_HALF_UP)m #(.multiply(b %)%2)a #(.add(b %)%2)s #(.subtract % %2)](-(int(nth(str(reduce(fn[z k](a z(m(d 1(.pow(b 16)k))(s(s(s(d 4(a 1(m 8 k)))(d 2(a 4(m 8 k))))(d 1(a 5(m 8 k))))(d 1(a 6(m 8 k)))))))(bigdec 0)(map bigdec(range(inc n)))))(+ n 2)))48)))48)))

因此,您可能会说,我不知道自己在做什么。这最终比任何东西都更可笑。我用Google将其“ pi转换为n位数字”,然后在Wikipedia页面上找到了Bailey–Borwein–Plouffe公式。我只知道微不足道的微积分(?)可以读取公式,所以设法将其转换为Clojure。

翻译本身并不难。由于公式要求(Math/pow 16 precision),难点在于处理高达n位的精度。变得非常快。我需要在BigDecimal所有地方都使用它来工作,这确实使事情变得肿了。

取消高尔夫:

(defn nth-pi-digit [n]
  ; Create some aliases to make it more compact
  (let [b bigdec
        d #(.divide (b %) %2 (+ n 4) BigDecimal/ROUND_HALF_UP)
        m #(.multiply (b %) %2)
        a #(.add (b %) %2)
        s #(.subtract % %2)]
    (- ; Convert the character representation to a number...
      (int ; by casting it using `int` and subtracting 48
         (nth ; Grab the nth character, which is the answer
           (str ; Convert the BigDecimal to a string
             (reduce ; Sum using a reduction
               (fn [sum k]
                 (a sum ; The rest is just the formula
                       (m
                         (d 1 (.pow (b 16) k))
                         (s
                           (s
                             (s
                               (d 4 (a 1 (m 8 k)))
                               (d 2 (a 4 (m 8 k))))
                             (d 1 (a 5 (m 8 k))))
                           (d 1 (a 6 (m 8 k)))))))
               (bigdec 0)
               (map bigdec (range (inc n))))) ; Create an list of BigDecimals to act as k
           (+ n 2)))
      48)))

不用说,如果您知道任何数学知识,那么我相信有一种更简单的方法可以解决此问题。

(for [t [0 1 2 3 10 100 599 760 1000 10000]]
  [t (nth-pi-digit t)])

([0 1] [1 4] [2 1] [3 5] [10 8] [100 8] [599 2] [760 4] [1000 3] [10000 5])

后来我意识到标准运算符实际上是对大十进制进行运算的,因此顶部的快捷方式是不必要的。我在某个时候安装此修复程序。这可能会导致〜50个字节。
致癌物质

2

Clojure,253个字节

(defmacro q[& a] `(with-precision ~@a))(defn h[n](nth(str(reduce +(map #(let[p(+(* n 2)1)a(q p(/ 1M(.pow 16M %)))b(q p(/ 4M(+(* 8 %)1)))c(q p(/ 2M(+(* 8 %)4)))d(q p(/ 1M(+(* 8 %)5)))e(q p(/ 1M(+(* 8 %)6)))](* a(-(-(- b c)d)e)))(range(+ n 9)))))(+ n 2)))

使用此公式计算数字pi 。必须重新定义宏,with-precision因为它使用得太频繁了。

您可以在此处查看输出:https : //ideone.com/AzumC3 1000和10000拍摄时间超出了对ideone使用的时间限制,耸了耸肩


2

Python 3,338字节

此实现基于Chudnovsky算法,该算法是估计pi的最快算法之一。对于每次迭代,估计大约有14位数字(更多信息请看这里)。

f=lambda n,k=6,m=1,l=13591409,x=1,i=0:not i and(exec('global d;import decimal as d;d.getcontext().prec=%d'%(n+7))or str(426880*d.Decimal(10005).sqrt()/f(n//14+1,k,m,l,x,1))[n+2])or i<n and d.Decimal(((k**3-16*k)*m//i**3)*(l+545140134))/(x*-262537412640768000)+f(n,k+12,(k**3-16*k)*m

在线尝试!


1

Java 7中,262 260个字节

import java.math.*;int c(int n){BigInteger p,a=p=BigInteger.TEN.pow(10010).multiply(new BigInteger("2"));for(int i=1;a.compareTo(BigInteger.ZERO)>0;p=p.add(a))a=a.multiply(new BigInteger(i+"")).divide(new BigInteger((2*i+++1)+""));return(p+"").charAt(n+1)-48;}

使用@LeakyNun的 Python 2算法

取消测试代码:

在这里尝试。

import java.math.*;
class M{
  static int c(int n){
    BigInteger p, a = p = BigInteger.TEN.pow(10010).multiply(new BigInteger("2"));
    for(int i = 1; a.compareTo(BigInteger.ZERO) > 0; p = p.add(a)){
      a = a.multiply(new BigInteger(i+"")).divide(new BigInteger((2 * i++ + 1)+""));
    }
    return (p+"").charAt(n+1) - 48;
  }

  public static void main(String[] a){
    System.out.print(c(0)+", ");
    System.out.print(c(1)+", ");
    System.out.print(c(2)+", ");
    System.out.print(c(3)+", ");
    System.out.print(c(10)+", ");
    System.out.print(c(100)+", ");
    System.out.print(c(599)+", ");
    System.out.print(c(760)+", ");
    System.out.print(c(1000)+", ");
    System.out.print(c(10000));
  }
}

输出:

1, 4, 1, 5, 8, 8, 2, 4, 3, 5

1

Smalltalk – 270字节

依靠身份tan⁻¹(x) = x − x³/3 + x⁵/5 − x⁷/7 ...,那π = 16⋅tan⁻¹(1/5) − 4⋅tan⁻¹(1/239)。SmallTalk使用无限精度整数算法,因此如果您愿意等待,它将适用于大型输入!

|l a b c d e f g h p t|l:=stdin nextLine asInteger+1. a:=1/5. b:=1/239. c:=a. d:=b. e:=a. f:=b. g:=3. h:=-1. l timesRepeat:[c:=c*a*a. d:=d*b*b. e:=h*c/g+e. f:=h*d/g+f. g:=g+2. h:=0-h]. p:=4*e-f*4. l timesRepeat:[t:=p floor. p:=(p-t)*10]. Transcript show:t printString;cr

pi.st在以下测试案例中另存为并运行。索引是基于之一的。

$ gst -q pi.st <<< 1
1
$ gst -q pi.st <<< 2
4
$ gst -q pi.st <<< 3
1
$ gst -q pi.st <<< 4
5
$ gst -q pi.st <<< 11
8
$ gst -q pi.st <<< 101
8
$ gst -q pi.st <<< 600
2
$ gst -q pi.st <<< 761
4
$ gst -q pi.st <<< 1001
3
$ gst -q pi.st <<< 10001 -- wait a long time!
5

1

JavaScript(Node.js)(Chrome 67 +),75 73 67 63字节

n=>`${eval(`for(a=c=100n**++n*20n,d=1n;a*=d;)c+=a/=d+++d`)}`[n]

在线尝试!

π/2=ķ=0ķ/2ķ+1个

n=>`${eval(`for(a=c=100n**n*20n,d=1n;a*=d;)c+=a/=d+++d`)}`[n]

JavaScript(Node.js)(Chrome 67+),90 89字节

n=>`${eval(`for(a=100n**++n*2n,b=a-a/3n,c=0n,d=1n;w=a+b;a/=-4n,b/=-9n,d+=2n)c+=w/d`)}`[n]

在线尝试!

π/4=Arctan1个/2+Arctan1个/3

n=>`${eval(`for(a=100n**n*2n,b=a-a/3n,c=0n,d=1n;w=a+b;a/=-4n,b/=-9n,d+=2n)c+=w/d`)}`[n]

0

枫树,24个字节

 trunc(10^(n+1)*Pi)mod 10

测试用例:

> f:=n->trunc(10^(n+1)*Pi)mod 10;
> f(0);
  1
> f(1);
  4
> f(2);
  1
> f(3);
  5
> f(10);
  8
> f(100);
  8
> f(599);
  2
> f(760);
  4
> f(1000);
  3
> f(10000);
  5

0

C#,252250字节

d=>{int l=(d+=2)*10/3+2,j=0,i=0;long[]x=new long[l],r=new long[l];for(;j<l;)x[j++]=20;long c,n,e,p=0;for(;i<d;++i){for(j=0,c=0;j<l;c=x[j++]/e*n){n=l-j-1;e=n*2+1;r[j]=(x[j]+=c)%e;}p=x[--l]/10;r[l]=x[l++]%10;for(j=0;j<l;)x[j]=r[j++]*10;}return p%10+1;}

在线尝试!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.