SRL Archive - OSR Help

Pi Script?


Sawyer

2013-03-14 22:39:42

I am trying to make a script to calculate pi. I am having toubles, but i am trying to use Leibniz's formula to do it. I have barely started, yet I am already getting errors.. Here's my code so far:
Program MathProblems;
var
Answer:Extended;

procedure PieMaker;
var
i:Integer;
x, d, e:Extended;
begin
i := 7;
x := ((2/3)+(1/5))-(1/i);
IncEx(i, 2);
d := (x) + (1/i);
Answer:= d;
Writeln(''+IntToStr(Answer)+'');
end;

begin
end.

rj

2013-03-14 22:42:18

there is a pi solver under competitions i cant link you to it atm though not on computer

Neodymium

2013-03-14 22:43:32

So, you are trying to convert answer, which is of type extended, as an integer to a string.
So, you need to find a function that will convert type extended to a string. I'm looking around.

EDIT: FloatToStr() is what you want to use in place of IntToStr().

rj

2013-03-14 22:45:17

From: Neodymium
So, you are trying to convert answer, which is of type extended, as an integer to a string.
So, you need to find a function that will convert type extended to a string. I'm looking around.


tostr(varhere)

Sawyer

2013-03-14 22:46:00

Ah. Yes I know there is already a script for it, but I am bored and wanted to make my own.
Ah Thanks :)

Neodymium

2013-03-14 22:50:32

From: RJJ95
tostr(varhere)


That works too I guess, I didn't know there was a generic string converter.
I always have to go though the trouble of typing inttostr(). ;|

Sawyer

2013-03-14 22:56:25

Ah. Yes I know there is already a script for it, but I am bored and wanted to make my own.
How does this look? (Using Leibniz's formula) It still gives me
"Exception in Script: Operator expected at line 18, column 1' (Line 18 is the Answer := (y + 2/3))
Program MathProblems;
var
Answer:Extended;

procedure PieMaker;
var
i:Integer;
x, d, e, y:Extended;
begin
i := 7;
x := 5;
repeat
e := (1/x) - (1/i);
IncEx(i, 2);
IncEx(x, 2);
y := (1/x) + (1/i);
until((x = 999))
Answer:= (y + (2/3));
ToStr(Answer);
Writeln(''+FloatToStr(Answer)+'');
end;

begin
PieMaker;
end.

Neodymium

2013-03-14 22:58:54

From: Sawyer
Ah. Yes I know there is already a script for it, but I am bored and wanted to make my own.
How does this look? (Using Leibniz's formula)
-snip-

Now you are trying to increment a float as an integer, I think you need to do something like

x := x + 2;
instead. I've run it just to test it out, and I get: "0.001001001001", in case you wanted to know.

Sawyer

2013-03-14 23:00:15

GAh… The 2/3 is missing.. darnit.. I'll work on it.
Leibniz's formula:
[ATTACH=CONFIG]19925[/ATTACH]

Note: X and I should not be extended, but integers :\

Neodymium

2013-03-14 23:14:57

From: Sawyer
GAh… The 2/3 is missing.. darnit.. I'll work on it.
Leibniz's formula:
[ATTACH=CONFIG]19925[/ATTACH]

Note: X and I should not be extended, but integers :\


Oh, so this is a series? I wonder if Simba has anything for that. :P

So I changed x to an integer as well, and put back the IncEx() call, but now I'm getting "0".
Something else is amiss.

Sawyer

2013-03-14 23:17:05

Program MathProblems;
var
Answer:Extended;

procedure PieMaker;
var
i, x:Integer;
d, e, y:Extended;
begin
i := 7;
x := 5;
repeat
e := (1/x) - (1/i);
IncEx(i, 2);
y := e + (1/i);
IncEx(i, 2);
d := y - (1/i);
Answer := ((d + 2/3)*4)
until(i = 999);
FloatToStr(Answer);
Writeln(''+FloatToStr(Answer)+'');
end;

begin
PieMaker;
end.
EDIT: Got 3.46265459826847 with this,

Neodymium

2013-03-14 23:20:24

From: Sawyer
-snip-
This I think would do it, but I am not sure how to writeln the answer.

Are you sure? I know you assign a value to Answer before the repeat loop, but you don't do anything with it afterwards.

Also, for writing the answer, I just threw in WriteLn(FloatToStr(Answer)) at the end of the main loop.

Sawyer

2013-03-14 23:27:08

From: Sawyer
Program MathProblems;
var
Answer:Extended;

procedure PieMaker;
var
i, x:Integer;
d, e, y, k:Extended;
begin
i := 7;
x := 5;
k := 1 - (1/3);
e := (k) + (1/x) - (1/i);
repeat
IncEx(x, 2);
IncEx(i, 2);
y := e + (1/i);
IncEx(i, 2);
IncEx(x, 2);
d := y - (1/i);
Answer := ((d)*4)
until(i = 999);
FloatToStr(Answer);
Writeln(''+FloatToStr(Answer)+'');
end;

begin
PieMaker;
end.
EDIT: Got 3.46265459826847 with this,

The formula is (1 - 1/3 + 1/5 - 1/7 + 1/9 … = pi/4) … it could be possible that this is impossible to do..

Neodymium

2013-03-14 23:50:17

Out of curiosity, I looked for Leibniz's formula on Wolfram. Didn't find it, but I did find another formula:
So, I just used that and came up with:

Program MathProblems;
var
Answer:Extended;

procedure PieMaker;
var
cycles, i: Integer;
begin
cycles := 300;
for i := 0 to cycles do
Answer := Answer + (pow(-1, i) / ((2 * i) + 1));
Answer := Answer * 4;
end;

begin
PieMaker;
Writeln(''+FloatToStr(Answer)+'');
end.
Just another way to do this I guess.

After changing the number of cycles to 10000, I get "3.14169264359054". Getting close. xD

Edit: Currently trying out 100 million cycles, its been about 3 minutes since the program started and my laptop is kicking into gear. :P

Edit 2: I'm fairly certain this is the same formula as your's, just in the form of a summation.

Edit 3: STILL GOING.

Edit 4: After 100 million cycles and almost 20 minutes, I got "3.14159266358979". :D

Sawyer

2013-03-15 00:23:39

Nice! :D I'm going to hit the sack :p but I'll work on mine tomorrow. Nice job!

Sawyer

2013-03-15 20:46:46

Interesting. It seems after my experiment with changing variables, I broke my simba :/ I redownloaded and copied most of my folders over though.

Sawyer

2013-03-16 14:15:02

From: core
I don't think that should happen… Did you manage to get it fixed?

I just redownloaded simba, copied various extensions/includes and my scripts over. I'm not sure what happened… After I was playing around with the math, I just kept getting "Exception in Script: Operator expected at line 453, column 93 in file "C:\Simba\Includes\SRL\SRL\core\gametab.simba" for ever single script. The scripts worked with the other simba however.

Smidqe

2013-03-16 14:37:53

From: Sawyer
I just redownloaded simba, copied various extensions/includes and my scripts over. I'm not sure what happened… After I was playing around with the math, I just kept getting "Exception in Script: Operator expected at line 453, column 93 in file "C:\Simba\Includes\SRL\SRL\core\gametab.simba" for ever single script. The scripts worked with the other simba however.


Make sure that interpreter is NOT set to Lape. Found under Script -> Interpreter.

Sawyer

2013-03-16 18:17:49

Oh Duh I feel dumb. *facepalm* Thanks :p

Richard

2013-03-16 20:12:57

No one has gone recursive? :(

I'll edit this post in a second with a recursive one for lols, shame that for loops can only increment by 1 or -1 in Pascal

Richard

2013-03-17 08:30:00

From: core
You can manually increment/decrement the variables using IncEx(variable,amount) and DecEx(variable, amount), or variable := variable +/- amt.

I tried to do a recursive implementation, but kept hitting out of memory errors on large numbers of cycles. Looking forward to your solution!


I know, but I enjoy using for loops, although not necessary for doing this recursively.

However, I seem to have run into a dead end, my code only ever seems to output 4.0, rather than the actual value of pi. I've even got to the point of using a pen and paper, and drawn out trace tables, and my algorithm should work. Makes me think I've done something wrong with types.

Sorry about the poor code, I haven't actually programmed in quite some time:
program new;
var
i: integer;
pi: extended;

const
depth = 120;

function pi2: extended;
begin
inc(i);
if (i = depth) then
result := 1 / ((2 * i) + 1)
else
if ((i mod 2) = 0) then
result := (1 / ((2 * i) + 1)) + pi2
else
result := (1 / ((2 * i) + 1)) - pi2;
end;

begin
pi := (4 * (1 - pi2));
writeln(floattostr(pi));
end.

Richard

2013-03-17 08:58:56

From: core
One error is that you're losing precision in your expressions.
If you change all of your to you should get results of the correct type… but I think there might be some other issue I haven't found yet. I'll update this post if I do.

Edits:


That does seem to have fixed it, I have a feeling it would be a type issue. Now it just turns out my maths was off :p

masterBB

2013-03-17 12:21:17

You can all go home now:

source: http://www.mathpropress.com/stan/bibliography/spigot.pdf
edited by me

Program Pi_Spigot;

const
n = 1000;
len = 10*n div 3;

var
i, j, k, q, x, nines, predigit: integer;
tm: integer;
a: array[1..len] of longint;
res: String;


begin
tm := getSystemTime;
for j := 1 to len do
a[j] := 2; {Start with 2s}
nines := 0;
predigit := 0; {First predigit is a 0}
for j := 1 to n do
begin
q := 0;
for i := len downto 1 do {Work backwards}
begin
x := 10*a[i] + q*i;
a[i] := x mod (2*i - 1);
q := x div (2*i - 1);
end;
a[1] := q mod 10;
q := q div 10;
if q = 9 then
nines := nines + 1
else
if q = 10 then
begin
res := res + ToStr(predigit+1);
for k := 1 to nines do
res := res + ToStr(0); {zeros}
predigit := 0;
nines := 0
end
else
begin
res := res + ToStr(predigit);
predigit := q;
if nines <> 0 then
begin
for k := 1 to nines do
res := res + ToStr(9);
nines := 0
end
end
end;
res := res + ToStr(predigit);
writeln('took ' + ToStr(getSystemTime- tm) + ' ms');
writeln(res);
end.

Sawyer

2013-03-17 12:36:47

Eh… Does that use Leibniz's Formula?

masterBB

2013-03-17 12:41:17

No, let me write it one sec

e:

okay, here it is:

function PiLeib(): Extended;
var
I:Integer;
begin
for I := 0 to 100000000 do
begin
Result := Result + (1.0 / ((I shl 2) + 1));
Result := Result - (1.0 / ((I shl 2) + 3));
end;

Result := Result * 4;
end;

masterBB

2013-03-17 14:19:37

But that is no longer the formula which was given to us :D. If that counts, so does the spigot algorithm I posted. Also you are comparing different stuff. I don't see how x iterations of your formula equals x iterations of mine. I won't let you win that easy ^^

We need more clear rules!

masterBB

2013-03-17 16:35:10

From: core
Au contraire, cher ami!

That is indeed the same formula, it is just restructured. The steps to arrive at it are outlined in my post before. Just multiplied it out and factored out a 2.


Ah, I am an idiot ;). Anyhow, results on my pc are different then yours, I get faster times with method. Reason is that processors aren't a fast with uints as they are with signed integers. But after optimizing your code by taking out * 16, yours was faster.

function corePi (m : uint32) : Extended;
var n : uint32;
begin
for n := 0 to m do
begin
result := result + 1.0 / (n * ((n shl 4) + 16) + 3)
end;
result := result * 8;
end;

masterBB

2013-03-17 17:18:24

From: core
I don't think its possible to go much faster with this formula


You thought wrong:

program new;

function corePi(m : uint32) : Extended;
var n : uint32;
begin
for n := 0 to m do
begin
result := result + 1.0 / (n * ((n * 16) + 16) + 3)
end;
result := result * 8;
end;

function corePi2(m : uint32) : Extended;
var n : uint32;
begin
for n := 0 to m do
begin
result := result + 1.0 / (n * ((n shl 4) + 16) + 3)
end;
result := result * 8;
end;

function corePi3(m : uint32) : Extended;
var n : Integer;
begin
for n := 0 to m do
result := result + 0.5 / ((n * (n + 1.0)) + 0.1875);
end

var
timez, i, trials, m:longint;
begin
trials := 10;
m := 10000000;

writeln('corePi: ' + FloatToStr(corePi(m)));
writeln('corePi2: ' + FloatToStr(corePi2(m)));
writeln('corePi3: ' + FloatToStr(corePi3(m)));

timez := GetTickCount;
for i:= 0 to trials do corePi(m);
writeln('corePi: ' + FloatToStr((GetTickCount-timez)/trials) + 'ms');

timez := GetTickCount;
for i:= 0 to trials do corePi2(m);
writeln('corePi2: ' + FloatToStr((GetTickCount-timez)/trials) + 'ms');

timez := GetTickCount;
for i:= 0 to trials do corePi3(m);
writeln('corePi3: ' + FloatToStr((GetTickCount-timez)/trials) + 'ms');

end.

e:

Results:
corePi: 3.14159260358979
corePi2: 3.14159260358979
corePi3: 3.14159260358979
corePi: 1748.8ms
corePi2: 1483.5ms
corePi3: 993.7ms

Richard

2013-03-17 18:36:38

Please tell me I'm not the only one who panicked when they saw the bitwise shifting? :p

I'm starting to get concerned about my competence for starting this degree in September…

masterBB

2013-03-17 19:05:20

From: Richard
Please tell me I'm not the only one who panicked when they saw the bitwise shifting? :p

I'm starting to get concerned about my competence for starting this degree in September…


Bitwise shifting is just a very fast multiply/divide operator. The only con is that you can only divide/multiply with powers of 2 (2, 4, 8, etc etc). There is also a restriction that it can only be used on integers, not on an extended for example

example:

10 shl 4 == 10 * 2^4 == 10 * 16

10 shr 3 == 10 / 2^3 == 10 / 8

Richard

2013-03-17 19:29:49

From: masterBB
Bitwise shifting is just a very fast multiply/divide operator. The only con is that you can only divide/multiply with powers of 2 (2, 4, 8, etc etc). There is also a restriction that it can only be used on integers, not on an extended for example

example:

10 shl 4 == 10 * 2^4 == 10 * 16

10 shr 3 == 10 / 2^3 == 10 / 8


Ah, I remember now, thank you :) It has been far too long since I've programmed. It's all very stressful

EDIT: Finally fixed my function doing it recursively. I don't know how to edit the stack size in Simba, so I did it in java. (you might want to edit the VM stack size to get some reasonable degree of accuracy with this)

public class Pi2 {

static int depth = 1000000;

public static void main(String[] args) {
double pi = 4.0 * pi2(-1);
System.out.print(pi);
}

private static double pi2(int i) {
i++;
if (i == depth)
return 1.0 / ((2.0 * i) + 1.0);
else
return Math.pow(-1, i) * (1.0 / ((2.0 * i) + 1.0)) + pi2(i);
}
}

Win.

masterBB

2013-03-18 07:00:07

From: Richard
Finally fixed my function doing it recursively.


function corePi4(m : uint32; n:Integer = 0) : Extended;
begin
* if n > m then
* * result := 0
* else
* * result := 0.5 / ((n * (n + 1.0)) + 0.1875) + corePi4(m, n+1);
end;
*

Note however that lape got a maximum amount of recursive calls it can do. Therefor this one will never be exact-ish.*

From: core
Always a pleasure to get schooled by masterBB! :)


It was also a pleasure to win. I enjoyed our script fight ^^ I like these kind of challenges. Next time I will beat you with a bigger distance for sure (nah, I can't pull this of twice) ;)

masterBB

2013-03-18 07:48:51

From: core
function corePi5(m : uint32) : Extended;
begin
result := 0.5 / ((m * (m + 1.0)) + 0.1875);
if m > 0 then
result := result + corePi4(m - 1);
end;

*Dusts off shoulders*


Ignoring that the code you posted is actually using my code ;) (+ corePi4) I improved it slightly, not really significant though.

function corePi6(m : Integer) : Extended;
begin
result := 0.5 / ((m * (m + 1)) + 0.1875);
if not(m = 0) then
result := result + corePi6(m - 1);
end;

edit:
note that I improved it for m numbers not much higher then 10000.

edit2:
my results were:
7.208 ms
6.396 ms

with 10000 m and 1000 t

masterBB

2013-03-18 07:58:12

From: core
This code does not produce results identical to all of the others, and is therefore invalid :p


Hmm, how strange. Your results don't match any of mine:
3.14154265858932
3.14154265858932
3.14154265858932

masterBB

2013-03-18 08:09:57

From: core
See my edit. I used m := 275052, which I believe is the highest m possible to run.


But what precision can we live with? The highest m mine was able to run with was 46340, because you tested it with 10000, I wanted to nail that test. My first quick write up was able to go much higher btw.

e:
after some testing I realized I am not going to make this much faster
so the winner is:
Core for a 46340 < m < 275052
Me for 0 < m < 46340

CynicRus

2013-03-18 08:27:50


under construction

Result:

Compiled successfully in 219 ms.
An = 3.6356761630528E-6
S(n-1) = 0.78539907231979
Pi/4 = 0.78539816339744
4*S(n-1) = 3.14159628927917
Pi = 3.14159265358979
Time:4.7ms
Successfully executed.

In LaPe.

masterBB

2013-03-18 08:38:02

From: core
(or someone significantly beats us here)


I am afraid another Russian joined this thread :S

masterBB

2013-03-18 09:18:37

From: core
is against all the rules!


The rules which have not been written, yet are so clear to us :P

CynicRus

2013-03-18 09:42:23


function GetPi(e: Extended; var Cnt : Integer): extended;
var
i,sng : Integer;
dx,res : Extended;
begin
I := 1;
Sng := 1;
dx := 1;

while Abs(dx) > Abs(e) Do
begin
Res := Res + dx;
Cnt:=Cnt+1;
i:=i+2;
Sng := Sng * (-1);
dx := Sng/I;
end;
Res := Res * 4;
Result:=Res;
end;

Output:

Compiled successfully in 234 ms.
Pi = 3.14159065358979
500000
Time:7.8ms
Successfully executed.

CynicRus

2013-03-18 09:44:54

From: core
We mingle with the unseen and dance with the ephemeral :)

I'm just curious as to why the super script is still "under construction"…


Because there is not considered to Leibniz. I've used a monte-carlo method:)

And you said that it is against the rules-)

masterBB

2013-03-18 10:33:46

From: CynicRus

function GetPi(e: Extended; var Cnt : Integer): extended;
var
i,sng : Integer;
dx,res : Extended;
begin
I := 1;
Sng := 1;
dx := 1;

while Abs(dx) > Abs(e) Do
begin
Res := Res + dx;
Cnt:=Cnt+1;
i:=i+2;
Sng := Sng * (-1);
dx := Sng/I;
end;
Res := Res * 4;
Result:=Res;
end;

Output:

Compiled successfully in 234 ms.
Pi = 3.14159065358979
500000
Time:7.8ms
Successfully executed.


In my bench:

corePi: 3.14159260358979
corePi2: 3.14159260358979
corePi3: 3.14159260358979
GetPi: 3.14159260358979
corePi: 1641.1ms
corePi2: 1435.2ms
corePi3: 996.9ms
GetPi: 1778.5ms

Richard

2013-03-18 11:08:29

From: masterBB
function corePi4(m : uint32; n:Integer = 0) : Extended;
begin
* if n > m then
* * result := 0
* else
* * result := 0.5 / ((n * (n + 1.0)) + 0.1875) + corePi4(m, n+1);
end;
*

Note however that lape got a maximum amount of recursive calls it can do. Therefor this one will never be exact-ish.*



It was also a pleasure to win. I enjoyed our script fight ^^ I like these kind of challenges. Next time I will beat you with a bigger distance for sure (nah, I can't pull this of twice) ;)


Yeah, that's the general issue with using this formula. This is why I did it in java in the end, because I don't know how to change the stack size in Simba.

However, even when editing the stack size, you still need to go to a huge depth of recursion to gain a reasonable degree of accuracy.

CynicRus

2013-03-19 01:03:38

From: core
We are the champions, my friend, even with Cynic's different algorithm!


function GetPi(m : integer) : extended;
var s : extended;
i : integer;
begin
s:=0;
for i:=0 to m do
s:=s+(pow((-1),i)*factorial(6*i)*(13591409 + 545140134*i))/(factorial(3*i)*pow(factorial(i),3)*pow(640320,3*i+3/2));
s := 1/(s * 12);
result:=s;
end;

var
timez: integer;
begin
timez:=GetTickCount;
WriteLn(' Pi = '+ToStr(GetPi(10)));
WriteLn('Time:'+FloatToStr((GetTickCount-timez)/10) + 'ms');
end.

Successfully executed.
Compiled successfully in 250 ms.
Pi = 3.14159265358979
Time:0ms
Successfully executed.

NKN

2013-03-19 06:46:02

From: CynicRus

function GetPi(m : integer) : extended;
var s : extended;
i : integer;
begin
s:=0;
for i:=0 to m do
s:=s+(pow((-1),i)*factorial(6*i)*(13591409 + 545140134*i))/(factorial(3*i)*pow(factorial(i),3)*pow(640320,3*i+3/2));
s := 1/(s * 12);
result:=s;
end;

var
timez: integer;
begin
timez:=GetTickCount;
WriteLn(' Pi = '+ToStr(GetPi(10)));
WriteLn('Time:'+FloatToStr((GetTickCount-timez)/10) + 'ms');
end.

Successfully executed.
Compiled successfully in 250 ms.
Pi = 3.14159265358979
Time:0ms
Successfully executed.


0 ms…? CAN YOU BEAT IT?!