Search code examples
c#stackpistack-machine

Approximation of PI with Brouncker's formula using a Stack machine


I'm working on how to translate this formula to obtain an approximation of PI (based on Brouncker's) to a stack machine.

The formula I'm working with is 4/(1 + 1^2/(2 + 3^2/(2 + 5^2/(2 + 7^2/(2 + 9^2/2))))) which is roughly 2.97. How can I translate this to stack machine code?

This is what I have so far, but it's wrong:

DIV
PUSH 4
DIV
ADD
PUSH 1
POW
PUSH 1
PUSH 2
DIV
ADD
POW 
PUSH 3
PUSH 2
PUSH 2
DIV
ADD
POW
PUSH 5
PUSH 2
PUSH 2
DIV
ADD
POW
PUSH 7
PUSH 2
PUSH 2
ADD
DIV
POW
PUSH 9
PUSH 2
PUSH 2
PUSH 2

(instructions are read from bottom to top)

It ends dividing 4 by 4.0909, but it should divide 4 by 1.344. There's some mathematical syntax that's wrong there, but I tried and haven't figured out where I'm wrong...

If needed, this is the class I've built for reading the instructions, it's in C# but it should be widely understood:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace Máquinas
{
    /**
    * @author toyomitsu
    *
    * @date - 2020.05.17 
    */
    public class StackMachine
    {
        private Stack<string> _Stack;
        private string[] _Instructions;

        public StackMachine(string[] Instructions)
        {
            Array.Reverse(Instructions);

            _Stack = new Stack<string>();
            _Instructions = Instructions;
        }

        public void PerformInstructions()
        {
            Console.WriteLine();
            Console.WriteLine("*** Stack machine ***");

            foreach (string Instruction in _Instructions)
            {
                string[] InstData = Instruction.Split(' ');

                switch (InstData[0])
                {
                    case "PUSH":
                        Push(InstData[1]);
                        break;

                    case "POP":
                        Pop();
                        break;

                    case "ADD":
                        Add();
                        break;

                    case "SUB":
                        Sub();
                        break;

                    case "MOD":
                        Mod();
                        break;

                    case "MUL":
                        Mul();
                        break;

                    case "DIV":
                        Div();
                        break;

                    case "POW":
                        Pow();
                        break;

                    case "SQR":
                        Sqr();
                        break;

                    case "EXP":
                        Exp();
                        break;

                    default:
                        continue;
                }

                List<string> Registry = _Stack.ToList<string>();

                Console.WriteLine();
                Console.WriteLine(string.Format("** Instruction: {0} **", Instruction));
                for (int i = 0; i < Registry.Count; i++)
                {
                    Console.WriteLine(string.Format("Registry {0}: {1}", i + 1, Registry[i]));
                }
                Console.WriteLine("**********************");
            }
        }

        #region Functions
        private void Push(string Data)
        {
            _Stack.Push(Data);
        }

        private string Pop()
        {
            return _Stack.Pop();
        }

        private void Add()
        {
            string Data1 = Pop();
            string Data2 = Pop();

            double Num1 = double.Parse(Data1, CultureInfo.InvariantCulture);
            double Num2 = double.Parse(Data2, CultureInfo.InvariantCulture);

            double Result = Num1 + Num2;
            Push(Result.ToString(CultureInfo.InvariantCulture));
        }

        private void Sub()
        {
            string Data1 = Pop();
            string Data2 = Pop();

            double Num1 = double.Parse(Data1, CultureInfo.InvariantCulture);
            double Num2 = double.Parse(Data2, CultureInfo.InvariantCulture);

            double Result = Num1 - Num2;
            Push(Result.ToString(CultureInfo.InvariantCulture));
        }

        private void Mul()
        {
            string Data1 = Pop();
            string Data2 = Pop();

            double Num1 = double.Parse(Data1, CultureInfo.InvariantCulture);
            double Num2 = double.Parse(Data2, CultureInfo.InvariantCulture);

            double Result = Num1 * Num2;
            Push(Result.ToString(CultureInfo.InvariantCulture));
        }

        private void Mod()
        {
            string Data1 = Pop();
            string Data2 = Pop();

            double Num1 = double.Parse(Data1, CultureInfo.InvariantCulture);
            double Num2 = double.Parse(Data2, CultureInfo.InvariantCulture);

            double Result = Num1 % Num2;
            Push(Result.ToString(CultureInfo.InvariantCulture));
        }

        private void Div()
        {
            string Data1 = Pop();
            string Data2 = Pop();

            double Num1 = double.Parse(Data1, CultureInfo.InvariantCulture);
            double Num2 = double.Parse(Data2, CultureInfo.InvariantCulture);

            double Result = Num1 / Num2;
            Push(Result.ToString(CultureInfo.InvariantCulture));
        }

        private void Pow()
        {
            string Data1 = Pop();
            string Data2 = Pop();

            double Num1 = double.Parse(Data1, CultureInfo.InvariantCulture);
            double Num2 = double.Parse(Data2, CultureInfo.InvariantCulture);

            double Result = Math.Pow(Num1, Num2);
            Push(Result.ToString(CultureInfo.InvariantCulture));
        }

        private void Sqr()
        {
            string Data1 = Pop();

            double Num1 = double.Parse(Data1, CultureInfo.InvariantCulture);

            double Result = Math.Sqrt(Num1);
            Push(Result.ToString(CultureInfo.InvariantCulture));
        }

        private void Exp()
        {
            string Data1 = Pop();

            double Num1 = double.Parse(Data1, CultureInfo.InvariantCulture);

            double Result = Math.Exp(Num1);
            Push(Result.ToString(CultureInfo.InvariantCulture));

        }
        #endregion
    }
}

Edit: I solved this. My math syntax was a mess. The correct stack machine is:

DIV
PUSH 4
ADD
PUSH 1
DIV
POW
PUSH 1
PUSH 2
ADD
PUSH 2
DIV
POW
PUSH 3
PUSH 2
ADD
PUSH 2
DIV
POW
PUSH 5
PUSH 2
ADD
PUSH 2
DIV
POW
PUSH 7
PUSH 2
ADD
PUSH 2
DIV
POW
PUSH 9
PUSH 2
PUSH 2

Solution

  • You've translated 2 + 7^2/(..x..) into x, 2, 2, 7, ^, +, / (where x is the temporary stack result)?

    Wouldn't that result in (2 + 7^2)/x? Don't you want x, 2, 7, ^, /, 2, +?