Jump to content

RPN Basic Calc


DreamVB
 Share

Recommended Posts

hi This is a Simple RPN expression evaluator, it uses a stack based method to compute the expression.

I know there maybe a few bugs that need ironing out that I try and figure out, as I want to try and make something with this anyway this is just the first version. Hope you may find it us full.

And here is the code

;Stack begin code
Local $stksize = 255
Local $stack[$stksize]
Local $stktop = -1

Func _isEmpty()
    Return ($stktop = -1)
EndFunc   ;==>_isEmpty

Func _isFull()
    Return ($stktop + 1 > $stksize - 1)
EndFunc   ;==>_isFull

Func _StkTop()
    Return $stksize
EndFunc   ;==>_StkTop

Func _Push($Value)
    If Not _isFull() Then
        $stktop += 1
        $stack[$stktop] = $Value
    EndIf
EndFunc   ;==>_Push

Func _Pop()
    Local $item
    $item = $stack[$stktop]
    $stktop -= 1
    Return $item
EndFunc   ;==>_Pop

;Stack end code

;Start of RPN calc
Func CalcRPN($exp)
    Local $x
    Local $c
    Local $Result = 0

    For $x = 1 To StringLen($exp)
        $c = StringMid($exp, $x, 1)
        If Not StringIsSpace($c) Then
            ;Check for Digits
            If StringIsDigit($c) Then
                ;Push digists onto the stack.
                _Push($c)
            EndIf
            ;Check for operators
            If StringInStr("+-/*", $c) Then
                Switch $c
                    Case "+"
                        ;Pop of two values, and add the results.
                        $Result = (_Pop() + _Pop())
                    Case "-"
                        ;Pop of two values, and subtract the results.
                        $Result = (_Pop() - _Pop())
                    Case "*"
                        ;Pop of two values, and times the results.
                        $Result = (_Pop() * _Pop())
                    Case "/"
                        ;Pop of two values, and devide the results.
                        $Result = (_Pop() / _Pop())
                EndSwitch
                ;Push back the result
                _Push($Result)
            EndIf
        EndIf
    Next
    Return $Result
EndFunc   ;==>CalcRPN

;Calc Postfix.
MsgBox(64, "RPN Calc-Demo", "Answer = " & CalcRPN("3 5 5 5 + * +"));Infix 1 test 3 + 5 * (5+5)
MsgBox(64, "RPN Calc-Demo", "Answer = " & CalcRPN("3 3 + 3 +"));Infix 2 test 3+3+3

On Error Resume Pulling Hair Out.

Link to comment
Share on other sites

Good start. Check out my Shunting-Yard example of how I did it.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

Hi here is a small update of my RPN Calculator.

Fixed problem that only allowed single numbers.

Added ^ operator.

And a few other fixes.

Code for Version 1.0a

;Reverse Polish Notation Calculator v1.0a

;Updated works now with any number.
;Added ^ power of operator

;Stack begin code
Local $stksize = 255
Local $stack[$stksize]
Local $stktop = -1
Local $idx

Func _StkRetset()
    ReDim $stack[$stksize]
    $st = -1
EndFunc   ;==>_StkRetset

Func _isEmpty()
    Return ($stktop = -1)
EndFunc   ;==>_isEmpty

Func _isFull()
    Return ($stktop + 1 > $stksize - 1)
EndFunc   ;==>_isFull

Func _StkTop()
    Return $stksize
EndFunc   ;==>_StkTop

Func _Push($Value)
    If Not _isFull() Then
        $stktop += 1
        $stack[$stktop] = $Value
    EndIf
EndFunc   ;==>_Push

Func _Pop()
    ;Pop item of the stack removing it.
    Local $item
    $item = $stack[$stktop]
    $stktop -= 1
    Return $item
EndFunc   ;==>_Pop

Func _Peek()
    ;Show item with out removeing it
    Return $stack[$stktop]
EndFunc   ;==>_Peek

;Stack end code

;Tokens stuff
Func StoreTokens($expr)
    Local $_Tokens[0]
    Local $count = 0
    $idx = 1
    While ($idx <= StringLen($expr))
        ;Reset token
        $Token = ""

        ;Skip white spaces
        _SkipWhite(StringMid($expr, $idx, 1))

        ;Check for digits
        If StringIsDigit(StringMid($expr, $idx, 1)) Then
            While StringIsDigit(StringMid($expr, $idx, 1))
                $Token &= StringMid($expr, $idx, 1)
                $idx += 1
            WEnd
        EndIf

        ;Check for operators
        If _IsOpSym(StringMid($expr, $idx, 1)) Then
            $Token = StringMid($expr, $idx, 1)
            $idx += 1
        EndIf

        If StringLen($Token) > 0 Then
            ReDim $_Tokens[$count + 1]
            ;Add token
            $_Tokens[$count] = $Token
            ;Get tokens count
            $count += 1
        EndIf

        ;Reset token.
        $Token = Null
    WEnd

    Return $_Tokens
    ReDim $_Tokens[0]
EndFunc   ;==>StoreTokens

Func _SkipWhite($c)
    If StringIsSpace($c) Then
        $idx += 1
    EndIf
EndFunc   ;==>_SkipWhite

Func _IsOpSym($c)
    Switch $c
        Case "(", ")"
            Return True
        Case "+", "-"
            Return True
        Case "*", "/"
            Return True
        Case "^"
            Return True
        Case Else
    EndSwitch
EndFunc   ;==>_IsOpSym

;Start of RPN calc
Func CalcRPN($Toks)
    Local $x
    Local $c
    Local $Result = 0

    For $x = 0 To UBound($Toks) - 1
        ;Get token
        $c = $Toks[$x]
        ;Check for Digits
        If StringIsDigit($c) Then
            ;Push digists onto the stack.
            _Push($c)
        EndIf
        ;Check for operators
        If _IsOpSym($c) Then
            Switch $c
                Case "+"
                    ;Pop of two values, and add the results.
                    $Result = (_Pop() + _Pop())
                Case "-"
                    ;Pop of two values, and subtract the results.
                    $Result = (_Pop() - _Pop())
                Case "*"
                    ;Pop of two values, and times the results.
                    $Result = (_Pop() * _Pop())
                Case "/"
                    ;Pop of two values, and devide the results.
                    $Result = (1 / _Pop() * _Pop())
                Case "^"
                    ;Power
                    Local $a = _Pop()
                    Local $b = _Pop()
                    $Result = ($b ^ $a)
            EndSwitch
            ;Push back the result
            _Push($Result)
        EndIf
    Next

    $Toks = Null
    Return $Result
EndFunc   ;==>CalcRPN

Local $Tokens[0]
;Get the tokens for the expression.
$Tokens = StoreTokens("102 10 +")
;Calc Postfix.
MsgBox(64, "RPN Calc-Demo", "Answer = " & CalcRPN($Tokens));Infix 1 test 102+10
;Calc Postfix.
$Tokens = StoreTokens("3 5 5 5 + * +")
MsgBox(64, "RPN Calc-Demo", "Answer = " & CalcRPN($Tokens));Infix 2 test 3 + 5 * (5+5)

;Calc Postfix.
$Tokens = StoreTokens("2 8 ^")
MsgBox(64, "RPN Calc-Demo", "Answer = " & CalcRPN($Tokens)) ;2 ^ 8

$Tokens = Null

On Error Resume Pulling Hair Out.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...