Digits of Pi

As I mentioned in other discussions, I don’t play games, but I do like to play with formulas and calculations. Long ago I posted a program that calculated the digits of Pi, but I haven’t been able to find it on the forum. I’m not referring to the one I posted a few days ago. The first program here might be the one I originally posted. It calculated 5,000 digits of Pi in 36.8 seconds on my iPad Air. Since then I’ve been playing around with other calculations and came up with the second program shown here. It calculates 5,000 digits of Pi in .67 seconds, an increase of about 55 times. I ran it for 100,000 digits which took 460 seconds. I’m not sure how many digits it can calculate before it overflows in a calculation.

Original program.

-- calculate digits of Pi

function setup()
    local digits=5000  -- number of digits of Pi
    print("Calculating "..digits.." digits of pi.")
    start=os.clock()
    local pi={}
    local tab={}
    local mf=math.floor
    local size=mf(digits)
    local size1=mf(size*6.8)
    local sum
    local carry
    local b
    for i=0,size1 do
        tab[i]=20
    end
    for t=1,size do
        carry=0
        for i=size1,0,-1 do
            sum=tab[i]*10+carry
            b=i*2+1
            tab[i]=sum%b
            carry=mf(sum/b)*i
        end       
        tab[0]=sum%10
        table.insert(pi,mf((sum)/10))
    end
    carry=0
    local x
    for z=size,1,-1 do
        x=pi[z]
        x=x+carry
        if x>9 then
            x=x-10
            carry=1
        else
            carry=0
        end
        pi[z]=string.format("%0d",x)
    end
    pi[1]="3.1"
    print(table.concat(pi))
    print()
    print(digits.." digits of Pi in")
    print(os.clock()-start,"seconds")
end

Update program.

-- calculate digits of Pi

function setup()
    local digits=5000  -- number of digits of Pi
    print("Calculating "..digits.." digits of pi.")
    start=os.clock()
    local pi={}
    local tab={}
    local size=math.ceil(digits/7)+1
    local size1=math.ceil(size*7)
    local sum
    local carry
    local b
    local d1=10000000
    local d2=9999999 
    local str=""
    for z=0,size1 do
        tab[z]=5*z+3
    end
    for t=1,size do
        carry=0
        for z=size1,0,-1 do
            sum=tab[z]*d1+carry
            b=27*z*z+27*z+6
            tab[z]=sum%b
            carry=(sum//b)*(2*z*z-z)
        end       
        tab[0]=sum%d1
        table.insert(pi,sum//d1)
    end
    carry=0
    for z=size,1,-1 do
        b=pi[z]+carry
        if b>d2 then
            b=b-d1
            carry=1
        else
            carry=0
        end
        pi[z]=string.format("%07d",b)
    end
    pi[1]="3."
    str=table.concat(pi)
    print(string.sub(str,1,digits+2))
    print(digits.."  digits of Pi in "..os.clock()-start,"seconds")
end

B)

I’m not sure about the 3,141th digit

@Cerea The Pi digits from position 3,130 to 3,150 from the Internet are 925201497442850732518. From my program they are 925201497442850732518. The 3,141st digit is a 2 in both numbers.

Hold on there, what about the 3,141,592nd digit?

I have a new iPad Pro that’s at least 10 times faster than my creaky ipad 2. I did some timings and have decided that the algorithm has a run time proportional to N**2. (Maybe I could have deduced that by reading the code.) That’s pretty good, but the fact that it took only 20 seconds to calculate pi to 40,000 places on something I can hold with two fingers is, well, astonishing.

@Ceres I’m not sure if the program will give the correct digits that high. I think it might start having overflow errors around 2 million digits, but I’m not sure. My iPad’s too slow to try that high. It took 50 seconds to do 40,000 on my iPad Air.

@dave1707 thanks for posting one of the most interesting things I’ve seen all year.

@Ceres Thanks for the comment. Later when I have more time, I’ll post a visual example of how the above program actually calculates each digit of Pi. You might find that even more interesting.

@Ceres Here’s the visual example of the Pi calculation. Slide the column parameter to calculate more digits of Pi. You can move the screen around when the size exceeds the screen size. Here’s a brief discription of how this works.

The 3 rows at the very top are calculated based on their column position. To calculate a digit of Pi, you start at the right most position of a row and do calculations to the left resulting in a digit of Pi. All calculations in a group affect the group to the left and the group just below it. I would try to explain it more, but I’ll let you read the link below that explains it. This example is based on the example shown at the link after you scroll down to Other formulas. If you have questions, just ask. http://www.pi314.net/eng/goutte.php

supportedOrientations(LANDSCAPE_ANY)

function setup()
    pi={}
    dist=40
    dx,dy=0,-60
    parameter.integer("columns",1,60,1)
    stroke(113, 59, 237, 255)
    strokeWidth(2)
    setup2()
    parameter.action("calc",setup2)
end

function setup2()
    size=columns-1
    pi={}
    sum={}
    sum[0]={}
    car={}
    car[0]={}
    v={}
    v[0]={}
    t={}
    t[0]={}
    x10={}
    x10[0]={}
    rem={}
    rem[0]={}
    for z=0,size do
        t[z]=z*(2*z-1)
        v[z]=3*(3*z+2)*(3*z+1)
        rem[0][z]=5*z+3
    end
    v[0]=10
    for d=1,columns do
        x10[d],car[d],sum[d],rem[d]={},{},{},{}
        car[d][size]=0
        for s=size,0,-1 do
            x10[d][s]=rem[d-1][s]*10
            sum[d][s]=x10[d][s]+car[d][s]
            rem[d][s]=sum[d][s]%v[s]
            car[d][s-1]=(sum[d][s]//v[s])*t[s]
            if s==0 then
                table.insert(pi,sum[d][0]//10)
            end
        end
    end
    sizeX=size
    digitsX=columns
end

function draw()
    background(224, 126, 152, 90)
    fontSize(30)
    fill(3, 0, 255, 255)
    text("Pi spigot",400+dx,HEIGHT+dy+10)
    fontSize(10)
    for s=0,sizeX do
        fill(255, 16, 0, 255)
        text(s+1,100+s*dist+dx,HEIGHT-15+dy)
        fill(255)
        text(t[s],100+s*dist+dx,HEIGHT-30+dy)
        text(v[s],100+s*dist+dx,HEIGHT-45+dy)
        text(rem[0][s],100+s*dist+dx,HEIGHT-60+dy)
    end
    text("A",75+dx,HEIGHT-30+dy)
    text("B",75+dx,HEIGHT-45+dy)
    text("Init",75+dx,HEIGHT-60+dy)
    for d=1,digitsX do
        fontSize(10)
        fill(255)
        for s=sizeX,0,-1 do
            text(x10[d][s],100+s*dist+dx,HEIGHT-d*60-15+dy)
            text(car[d][s],100+s*dist+dx,HEIGHT-d*60-30+dy)
            text(rem[d][s],100+s*dist+dx,HEIGHT-d*60-60+dy)
            if s==0 then
                fill(16, 255, 0, 255)
            end
            text(sum[d][s],100+s*dist+dx,HEIGHT-d*60-45+dy)

        end 
        fill(255)
        text("x10",75+dx,HEIGHT-d*60-15+dy)
        text("car",75+dx,HEIGHT-d*60-30+dy)
        text("sum",75+dx,HEIGHT-d*60-45+dy)
        text("rem",75+dx,HEIGHT-d*60-60+dy)
        text(d..".)",10+dx,HEIGHT-d*60-50+dy)
        fontSize(30)
        fill(244, 255, 0, 255)
        if d==1 then
            text(".",55+dx,HEIGHT-d*60-50+dy)
        end
        text(sum[d][0]//10,40+dx,HEIGHT-d*60-50+dy)
        line(dx,HEIGHT-d*60+dy-8,sizeX*dist+120+dx,HEIGHT-d*60+dy-8)
    end
    fontSize(16)
    for a,b in pairs(pi) do
        text(b,a*12+dx,HEIGHT+dy+40)
        if a==1 then
            text(".",a*12+6+dx,HEIGHT+dy+40)
        end
    end
end

function touched(t)
    if t.state==MOVING then
        dx=dx+t.deltaX
        dy=dy+t.deltaY
    end
end