Question

For a school's assignment I am trying to calculate pi using the Gauss Legendre algorithm to test cpu efficiency. Therefore, I have written a program in Ruby. This program should iterate 500000000 times and display the the time used for it. But everytime it executes within a second. My question: Is there a better way to iterate so it really does repeat 500 million times and display pi and the time?

include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
start = Time.now
until i = imax
    an = (a/2) + (b/2)
    bn = sqrt(a) * sqrt(b)
    tn = t - p * ((a-an) * (a-an))
    pn = 2 * p
    a = an
    b = bn
    t = tn
    p = pn
    i +=1
    PI = ((a+b)*(a+b))/(4*t)
end
finish = Time.now
time = finish - start
puts PI
puts time
Was it helpful?

Solution 2

In addition to the issues raised by @Nick and @sawa your algorithm is flawed: the square root of the product of a and b is not equal to the product of the square roots of a and b.

In ruby:

include Math
a, b, t, p = 1, 1/sqrt(2), 0.25, 1
imax = 5
imax.times do |i|
    an = (a+b) / 2
    bn = sqrt(a * b)
    tn = t - p * ((a-an) * (a-an))
    pn = 2 * p
    a, b, t, p = an, bn, tn, pn
    pi = ((a+b)*(a+b))/(4*t)
    printf "%d : %10.60f\n", i, pi
end

Running this gives me:

0 : 3.140579250522168575088244324433617293834686279296875000000000
1 : 3.141592646213542838751209274050779640674591064453125000000000
2 : 3.141592653589794004176383168669417500495910644531250000000000
3 : 3.141592653589794004176383168669417500495910644531250000000000
4 : 3.141592653589794004176383168669417500495910644531250000000000

So clearly you need more accuracy, hence BigDecimal. As this is your homework assignment I'll leave that up to you :-). (If unsure which variables to change, try all except i and imax. Also check out http://www.ruby-doc.org/stdlib-1.9.3/libdoc/bigdecimal/rdoc/BigDecimal.html)

OTHER TIPS

Start by not making i equal imax right away:

until i = imax

Should be

until i == imax

Even better, just do

500000000.times do

Instead of that line.

Another thing you are doing wrong is assigning a constant PI within a loop. Although it is possible to reassign a constant, it is not correct to do so. Either use a variable or move the assignment to outside of the loop so that it would be assigned only once.

Even if I remove the assignment and print out the result for each iteration like this:

include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
until i == imax
    an = (a/2) + (b/2)
    bn = sqrt(a) * sqrt(b)
    tn = t - p * ((a-an) * (a-an))
    pn = 2 * p
    a = an
    b = bn
    t = tn
    p = pn
    i +=1
    puts ((a+b)*(a+b))/(4*t)
end

I get the wrong result. It goes like this:

-2.1244311544725596
-1.1383928808463357
-1.1265990444799223
-1.1265961703346379
-1.126596170334544
-1.126596170334544
... # very long repetition of the same number
-1.126596170334544
-1.126596170334544
NaN
NaN
... # NaN forever

Something must be wrong with your algorithm.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top