DEV Community

Discussion on: TIL: Calculating n digits of pi using Chudnovsky Algorithm

Collapse
 
lysergikproductions profile image
LysergikProductions • Edited

I rewrote the code for use directly in a Terminal by simply running $ python3 [scriptTitle].py [number of iterations to perform]

This code also prevents unnecessary iterations by checking when the last 10 iterations have not updated the accuracy of the requested number of digits.

"""
pi.py
# 2020 (C) Nikolas A. Wagner
# License: GNU GPLv3

# Build_010

                   -- Purpose --
 Stress test CPU for its single-threaded performance

 """
 # setting global variables
import time; import decimal
import os; import sys

txtPi = ""; final_k = 1; its = 1; n = 0
decimalArgs = decimal.Decimal(0)
validArgs = True; startTime = None

# evaluate the command line arguments and set flags for MAIN
def INIT():
    os.system('clear && printf "Initializing..\n"')
    global decimalArgs; global validArgs; global startTime

    try:
        args = int(sys.argv[1]); print(args)
        decimalArgs = decimal.Decimal(args)
    except:
        print("""I can't do that! I need a whole number with no extra symbols!\n""")
        validArgs = False; return
    finally:
        if decimalArgs < 34:
            decimalArgs = 34
            print('Sorry, but I can only be accurate from 34 digits onward.')
            os.system('sleep 2')

        elif decimalArgs > 10000000:
            decimalArgs = 10000000
            print('For the sake of your Terminal, I will limit you to 10 MIL. Edit code to change this if you insist.')
            os.system('sleep 2')

    startTime = time.time()

INIT()

# define functions; finally calling MAIN()
def getUptime():
    return time.time() - startTime

def compute_pi(n):
    global final_k; global txtPi
    decimal.getcontext().prec = n + 1
    its = n; n += 1

    x = 0
    C = 426880 * decimal.Decimal(10005).sqrt()

    K = 6.0; M = 1.0; X = 1
    L = 13591409; S = L

    for k in range(1, n):
        if x == 0:
            print('calculating k= {0}..\n'.format(k - 1))

        lastPi = decimal.Decimal(C / S)
        M = M * (K ** 3 - 16 * K) / ((k + 1) ** 3)
        L += 545140134
        X *= -262537412640768000
        S += decimal.Decimal(M * L) / X
        pi = decimal.Decimal(C / S)

        os.system('clear')
        print('{0}\n'.format(pi))

        if lastPi != pi:
            print('Accuracy improved from iteration {0}'.format(k))
            final_k = k
        else:
            x += 1; n+= 1
            print("Pi not changed {0} time/s".format(x))

            if x >= 10:
                os.system('history -c && clear')
                print(pi); txtPi = str(pi)
                print("\n{0} digits of precision achieved in {1} iterations!".format(its, final_k))
                return ""

def MAIN():
    global validArgs

    if validArgs == True:
        result = compute_pi(int(decimalArgs)); print(result)
        f = open('pi.txt', 'w+'); f.write(txtPi)

        uptime = str(getUptime())
        print("This took {0} seconds".format(uptime))

        print("""
    The last one to three digits are tentative
    The decimal module rounds digits of precision rather than trimming them
""")

    else:
        print('INIT failed; please try again!')

MAIN()