1000 digits of pi in Python
Asked Answered
B

11

27

I have been thinking about this issue and I can't figure it out. Perhaps you can assist me. The problem is my code isn't working to output 1000 digits of pi in the Python coding language.

Here's my code:

def make_pi():
    q, r, t, k, m, x = 1, 0, 1, 1, 3, 3
    while True:
        if 4 * q + r - t < m * t:
            yield m
            q, r, t, k, m, x = (10*q, 10*(r-m*t), t, k, (10*(3*q+r))//t - 10*m, x)
        else:
            q, r, t, k, m, x = (q*k, (2*q+r)*x, t*x, k+1, (q*(7*k+2)+r*x)//(t*x), x+2)

digits = make_pi()
pi_list = []
my_array = []
for i in range(1000):
    my_array.append(str("hello, I'm an element in an array \n" ))
big_string = "".join(my_array)

print "here is a big string:\n %s" % big_string 

I know this code can be fixed to work, but I'm not sure what to fix... The print statement saying here is a big string and the my_array.append(str("hello, im an element in an array \n)) is just a filler for now. I know how all the code is used to work, but like I said before, I can't get it to shoot out that code.

Boyhood answered 25/1, 2012 at 14:59 Comment(7)
that looks like a version of pi spigot algorithm, is it in fact?Florri
Could you be a little clearer as to what the problem is; how does the behavior differ from what you expected?Kaylyn
The code looks suspiciously like the code here and here.Nose
This question seems really familiar. Was it asked here before and deleted?Kalpak
It is a version of the pi spigot algorithm XD. The output behavior doesn't work at all...what else is there to say. The question is similar because I asked it before then deleted it due to bad ratings, and the question was closed when in fact it was not answered....Boyhood
related: Gauss-Legendre Algorithm in pythonPhelps
change line my_array.append(str("hello, I'm an element in an array \n" )) to: my_array.append(digits.next())Bereave
C
27

Run this

def make_pi():
    q, r, t, k, m, x = 1, 0, 1, 1, 3, 3
    for j in range(1000):
        if 4 * q + r - t < m * t:
            yield m
            q, r, t, k, m, x = 10*q, 10*(r-m*t), t, k, (10*(3*q+r))//t - 10*m, x
        else:
            q, r, t, k, m, x = q*k, (2*q+r)*x, t*x, k+1, (q*(7*k+2)+r*x)//(t*x), x+2


my_array = []

for i in make_pi():
    my_array.append(str(i))

my_array = my_array[:1] + ['.'] + my_array[1:]
big_string = "".join(my_array)
print "here is a big string:\n %s" % big_string 

And read about yield operator from here: What does the "yield" keyword do?

Here is the answer:

3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337
Chelton answered 25/1, 2012 at 15:22 Comment(6)
I have a crazy idea to turn a Raspberry Pi loose on calculating pi out to many millions of places by letting it run 24/7 for years. The info presented in this question/answer seems very helpful. Thanks for posting this. I ran the code with a range of 50000 and it finished but I don't know if it is accurate. No errors were generated. Need to figure out how to deal with off loading partial results to disk rather than keeping it in memory.Gibbons
The "for j in range(1000)" makes it generate far fewer than 1000 digits. That should be changed back to "while True" or some other condition.Sweptback
I really do not like this code, fist - you change "make_pi" function with some limits without even trying to extract it to parameters, but even this is not needed - make_pi() return a generator and you can read from it using .next() as many times as you want, second why to call to make_pi twice?Bereave
Any explanation, why this code is supposed to give PI, except for trying it? It is very unreadable. It reminds me of a transformation used for generating Fibonacci numbers in logarithmic time.Marciemarcile
why have you declared pi_list and assigned digits without using them? That's just confusing.Preraphaelite
By doing j in range(4319), this answer will give 1000 digitsKizzee
S
38

If you don't want to implement your own algorithm, you can use mpmath.

try:
    # import version included with old SymPy
    from sympy.mpmath import mp
except ImportError:
    # import newer version
    from mpmath import mp

mp.dps = 1000  # set number of digits
print(mp.pi)   # print pi to a thousand places

Reference

Update: Code supports older and newer installations of SymPy (see comment).*

Shipshape answered 9/11, 2012 at 22:30 Comment(1)
When you install sympy in an environment like the ones created by anaconda, it will install mpmath separately and the import statement becomes from mpmath import mp. The code in this answer does not work anymore with modern versions of sympy. There is no sympy.mpmath anymore.Marciemarcile
C
27

Run this

def make_pi():
    q, r, t, k, m, x = 1, 0, 1, 1, 3, 3
    for j in range(1000):
        if 4 * q + r - t < m * t:
            yield m
            q, r, t, k, m, x = 10*q, 10*(r-m*t), t, k, (10*(3*q+r))//t - 10*m, x
        else:
            q, r, t, k, m, x = q*k, (2*q+r)*x, t*x, k+1, (q*(7*k+2)+r*x)//(t*x), x+2


my_array = []

for i in make_pi():
    my_array.append(str(i))

my_array = my_array[:1] + ['.'] + my_array[1:]
big_string = "".join(my_array)
print "here is a big string:\n %s" % big_string 

And read about yield operator from here: What does the "yield" keyword do?

Here is the answer:

3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337
Chelton answered 25/1, 2012 at 15:22 Comment(6)
I have a crazy idea to turn a Raspberry Pi loose on calculating pi out to many millions of places by letting it run 24/7 for years. The info presented in this question/answer seems very helpful. Thanks for posting this. I ran the code with a range of 50000 and it finished but I don't know if it is accurate. No errors were generated. Need to figure out how to deal with off loading partial results to disk rather than keeping it in memory.Gibbons
The "for j in range(1000)" makes it generate far fewer than 1000 digits. That should be changed back to "while True" or some other condition.Sweptback
I really do not like this code, fist - you change "make_pi" function with some limits without even trying to extract it to parameters, but even this is not needed - make_pi() return a generator and you can read from it using .next() as many times as you want, second why to call to make_pi twice?Bereave
Any explanation, why this code is supposed to give PI, except for trying it? It is very unreadable. It reminds me of a transformation used for generating Fibonacci numbers in logarithmic time.Marciemarcile
why have you declared pi_list and assigned digits without using them? That's just confusing.Preraphaelite
By doing j in range(4319), this answer will give 1000 digitsKizzee
S
9

The accepted answer is incorrect, as noted in comments.

The OP's code appears to be based on an implementation of Spigot's algorithm copied from here.

To fix the code per the OP's question (although I renamed the variables and functions to match what they were in the original source), one solution might be:

#!/usr/bin/env python

DIGITS = 1000

def pi_digits(x):
    """Generate x digits of Pi."""
    q,r,t,k,n,l = 1,0,1,1,3,3
    while x >= 0:
        if 4*q+r-t < x*t:
            yield n
            x -= 1
            q,r,t,k,n,l = 10*q, 10*(r-n*t), t, k, (10*(3*q + r))/t-10*n, l
        else:
            q,r,t,k,n,l = q*k, (2*q+r)*l, t*l, k+1, (q*(7*k+2)+r*l)/(t*l), l+2

digits = [str(n) for n in list(pi_digits(DIGITS))]
print("%s.%s\n" % (digits.pop(0), "".join(digits)))

Also, here is a much faster* implementation, also apparently based on Spigot's algorithm:

#!/usr/bin/env python

DIGITS = 1000

def pi_digits(x):
    """Generate x digits of Pi."""
    k,a,b,a1,b1 = 2,4,1,12,4
    while x > 0:
        p,q,k = k * k, 2 * k + 1, k + 1
        a,b,a1,b1 = a1, b1, p*a + q*a1, p*b + q*b1
        d,d1 = a/b, a1/b1
        while d == d1 and x > 0:
            yield int(d)
            x -= 1
            a,a1 = 10*(a % b), 10*(a1 % b1)
            d,d1 = a/b, a1/b1

digits = [str(n) for n in list(pi_digits(DIGITS))]
print("%s.%s\n" % (digits.pop(0), "".join(digits)))

I tested both a few times against this online Pi digit generator.

All credit to this Gist by deeplook.

* Based on testing 10,000 digits, where I got about 7 seconds compared to about 1 second.

Stroman answered 3/3, 2019 at 9:25 Comment(0)
T
4

For up to 1 million digits of pi use math_pi (note: I am the author of the module)

Install with pip:

pip install math-pi

In Python:

>>> import math_pi
>>> print(math_pi.pi(b=1000))
3.1415926535...
Tareyn answered 24/6, 2020 at 12:39 Comment(0)
O
3

From Fabrice Bellard site: Pi Computation algorithm. Sorry for such a straightforward implementation. 1000 is fast enough (0.1s for me), but 10000 isn't such fast - 71s :-(

import time
from decimal import Decimal, getcontext

def compute(n):
    getcontext().prec = n
    res = Decimal(0)
    for i in range(n):
        a = Decimal(1)/(16**i)
        b = Decimal(4)/(8*i+1)
        c = Decimal(2)/(8*i+4)
        d = Decimal(1)/(8*i+5)
        e = Decimal(1)/(8*i+6)
        r = a*(b-c-d-e)
        res += r
    return res

if __name__ == "__main__":
    t1 = time.time()
    res = compute(1000)
    dt = time.time()-t1
    print(res)
    print(dt)
Officiary answered 21/7, 2019 at 11:50 Comment(0)
L
2

I was solved with bellow formula 5-6 years ago.

Machin-like formula

Wikipedia: https://en.wikipedia.org/wiki/Machin-like_formula

Math formula

Sorry for the code quality. Variable names can be meaningless.

#-*- coding: utf-8 -*-

# Author:    Fatih Mert Doğancan
# Date:      02.12.2014

def arccot(x, u):
    sum = ussu = u // x
    n = 3
    sign = -1
    while 1:
        ussu = ussu // (x*x)
        term = ussu // n
        if not term:
            break
        sum += sign * term
        sign = -sign
        n += 2
    return sum

def pi(basamak):
    u = 10**(basamak+10)
    pi = 4 * (4*arccot(5,u) - arccot(239,u))
    return pi // 10**10

if __name__ == "__main__":
    print pi(1000) # 1000 
Laurellaurella answered 27/1, 2020 at 11:14 Comment(0)
L
1

I'm not familiar with your algorithm. Is it an implementation of BBP?

In any case, your make_pi is a generator. Try using it in a for loop:

for digit in make_pi():
    print digit

Note that this loop is infinite: make_pi() never throws StopIteration

Leeth answered 25/1, 2012 at 15:8 Comment(1)
the algorithm is based on the Spigot_algorithm: en.wikipedia.org/wiki/Spigot_algorithmAramen
E
1

Here you can check whether your program outputs correct 1000 digits: http://spoj.com/CONSTANT

Of course you can use diff or tc as well but you'd have to copy these 1000 digits from somewhere and there you just submit your program and check whether the score is bigger than 999.

You can try to print even more digits there and thus get more points. Perhaps you'd enjoy it.

Emilioemily answered 1/12, 2014 at 13:16 Comment(0)
K
0

Does this do what you want?

i = 0;
pi_str = ""
for x in make_pi():
    pi_str += str(x)
    i += 1
    if i == 1001:
        break

print "pi= %s.%s" % (pi_str[0],pi_str[1:])
Kaylyn answered 25/1, 2012 at 15:14 Comment(0)
D
0

Here is a different way I found here --> Python pi calculation? to approximate python based on the Chudnovsky brothers formula for generating Pi which I have sightly modified for my program.

def pifunction():
    numberofdigits = int(input("please enter the number of digits of pi that you want to generate"))
    getcontext().prec = numberofdigits

def calc(n):
    t = Decimal(0)
    pi = Decimal(0)
    deno = Decimal(0)
    k = 0
    for k in range(n):
        t = (Decimal(-1)**k)*(math.factorial(Decimal(6)*k))*(13591409+545140134*k)
        deno = math.factorial(3*k)*(math.factorial(k)**Decimal(3))*(640320**(3*k))
        pi += Decimal(t)/Decimal(deno)
    pi = pi * Decimal(12)/Decimal(640320**Decimal(1.5))
    pi = 1/pi
    return str(pi)
print(calc(1))

I hope this helps as you can generate any number of digits of pi that you wish to generate.

Diaper answered 22/10, 2015 at 21:11 Comment(2)
If I remove the first "def pifunction():" so that it runs without syntax error, the answer is only accurate to about 13 places: 3.1415926535897342076Sweptback
That is because of the parameter on the last line. Put in a 2 and it does much better, and so on. Function pifunction() is not used and would not directly affect the accuracy of the calculation, only the precision. On the other hand, this method converges very quickly and because terms alternate in sign, you get bounds on the true value.Jeremiahjeremias
G
0

wallis formula can get to 3.141592661439964 but a more efficient way is needed to solve this problem.

https://www.youtube.com/watch?v=EZSiQv_G9HM

and now my code

x, y, summing = 2, 3, 4

for count in range (0,100000000):
    summing *= (x/y)
    x += 2
    summing *= (x/y)
    y += 2

print (summing)
Gipsy answered 16/1, 2018 at 3:0 Comment(2)
because of integer divide, this works only in Python3Walters
@Walters but python 2.x is now discontinuedGiacopo

© 2022 - 2024 — McMap. All rights reserved.