Jump to content

# My rpn calculator can't compute negative numbers...

Go to solution Solved by jchd,

## Recommended Posts

hi everyone!

I need some help with my rpn calculator.

I first translated it from vbscript to autoitscript and that's when i stumbled on problem one:

(46) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:

\$Stack[ubound(\$Stack)] = \$Item

^ ERROR

After that (and i know this from testing it as a vbscript) it can't work with negative numbers:

"1 - - 2" to Reverse Polish notation = "1 - 2 -" gives me the build in error...

Can you guy's help me with my code pleas?

```Func Print(\$what,\$er = 0)
\$t = ''
if \$err <> 0 then \$t = 'ERROR!'
MsgBox(\$er,\$st,\$what)
EndFunc

Func RPN(\$Tokenarray)
Local \$Stack = []
Local \$Result
Local \$Operator_B
Local \$Operator_A

For \$Token = 0 To Ubound(\$Tokenarray)
If Isoperator(\$Tokenarray[\$Token]) Then
\$Operator_B = Pop(\$Stack)
\$Operator_A = Pop(\$Stack)
If \$Operator_A = "" Then
Print("The user has not input sufficient values in the expression.",16)
exit
EndIf
Switch \$Tokenarray[\$Token]
Case "+"
\$Result = Number(\$Operator_A,3) + Number(\$Operator_B,3)
Case "-"
\$Result = Number(\$Operator_A,3) - Number(\$Operator_B,3)
Case "*"
\$Result = Number(\$Operator_A,3) * Number(\$Operator_B,3)
Case "/"
\$Result = Number(\$Operator_A,3) / Number(\$Operator_B,3)
Case "^"
\$Result = Number(\$Operator_A,3) ^ Number(\$Operator_B,3)
EndSwitch
Push(\$Result,\$Stack)
Else
Push(\$Tokenarray[\$Token],\$Stack)
EndIf
Next
If Ubound(\$Stack) > 1 Then
Print("The user input has too many values.",16)
Exit
EndIf
Return pop(\$Stack)
EndFunc

Func Push(\$Item, Byref \$Stack)
If Ubound(\$Stack) > -1 Then
Redim \$Stack[Ubound(\$Stack) + 1]
\$Stack[Ubound(\$Stack)] = \$Item
Else
Local \$Stack = [\$Item]
EndIf
EndFunc

Func Pop(\$Stack)
\$pop = ""
If Ubound(\$Stack) > -1 Then
\$Pop = \$Stack[Ubound(\$Stack)]
Redim \$Stack[Ubound(\$Stack) - 1]
EndIf
Return \$pop
EndFunc

Func Peek(\$Stack)
\$peek = ""
If Ubound(\$Stack) > -1 Then
\$Peek = \$Stack(Ubound(\$Stack))
EndIf
Return \$peek
EndFunc

Func Isoperator(\$Operator)
Return StringInstr("+-*/^&<=>", \$Operator) <> 0 And StringLen(\$Operator) = 1
EndFunc

Func Precedence(\$Operator)
If Isoperator(\$Operator) Then
Switch \$Operator
case "^"
Return 4
case "*","/"
Return 3
case "+","-"
Return 2
case "&"
Return 1
case "<","=",">"
Return 0
EndSwitch
EndIf
EndFunc

;##################################################################################################

; (4 - -5) = (4|-|-|5) = (4|-|5|-)
;  input      tokens        rpn
Global \$calculate_this = ["4","-","5","-"]

Print(rpn(\$calculate_this))```

thanks in advance ,

TheAutomator

Edited by TheAutomator
##### Share on other sites

Without reading the code I'd say

\$Stack[ubound(\$Stack)] = \$Item

should be

\$Stack[ubound(\$Stack) -1 ] = \$Item

Which is the highest index of the array.

EDIT:

Also, I can tell you that

If Ubound(\$Stack) > -1 Then will always be true, assuming it is actually an array.

Edited by JohnOne

Monkey's are, like, natures humans.

##### Share on other sites

Without reading the code I'd say

\$Stack[ubound(\$Stack)] = \$Item

should be

\$Stack[ubound(\$Stack) -1 ] = \$Item

Which is the highest index of the array.

EDIT:

Also, I can tell you that

If Ubound(\$Stack) > -1 Then will always be true, assuming it is actually an array.

but aren't array's 0 based if you declare them that way?

##### Share on other sites

Local \$Stack[10]

UBound(\$Stack) equals 10, but the highest element is [9] including [0]

Monkey's are, like, natures humans.

##### Share on other sites

Local \$Stack[10]

UBound(\$Stack) equals 10, but the highest element is [9] including [0]

got it, thanks JohnOne!

problem one: Solved

```Func Print(\$what,\$er = 0)
MsgBox(\$er,'',\$what)
EndFunc

Func RPN(\$Tokenarray)
Local \$Stack = []
Local \$Result
Local \$Operator_B
Local \$Operator_A

For \$Token = 0 To Ubound(\$Tokenarray) - 1
If Isoperator(\$Tokenarray[\$Token]) Then
\$Operator_B = Pop(\$Stack)
\$Operator_A = Pop(\$Stack)
If \$Operator_A = "" Then
Print("The user has not input sufficient values in the expression.",16)
exit
EndIf
Switch \$Tokenarray[\$Token]
Case "+"
\$Result = Number(\$Operator_A,3) + Number(\$Operator_B,3)
Case "-"
\$Result = Number(\$Operator_A,3) - Number(\$Operator_B,3)
Case "*"
\$Result = Number(\$Operator_A,3) * Number(\$Operator_B,3)
Case "/"
\$Result = Number(\$Operator_A,3) / Number(\$Operator_B,3)
Case "^"
\$Result = Number(\$Operator_A,3) ^ Number(\$Operator_B,3)
EndSwitch
Push(\$Result,\$Stack)
Else
Push(\$Tokenarray[\$Token],\$Stack)
EndIf
Next
If Ubound(\$Stack) - 1 > 1 Then
Print("The user input has too many values.",16)
Exit
EndIf
Return pop(\$Stack)
EndFunc

Func Push(\$Item, Byref \$Stack)
If Ubound(\$Stack) > -1 Then
Redim \$Stack[Ubound(\$Stack) + 1]
\$Stack[Ubound(\$Stack) - 1] = \$Item
Else
Local \$Stack = [\$Item]
EndIf
EndFunc

Func Pop(\$Stack)
\$pop = ""
If Ubound(\$Stack) > -1 Then
\$Pop = \$Stack[Ubound(\$Stack) - 1]
Redim \$Stack[Ubound(\$Stack) - 2]
EndIf
Return \$pop
EndFunc

Func Peek(\$Stack)
\$peek = ""
If Ubound(\$Stack) > -1 Then
\$Peek = \$Stack[Ubound(\$Stack) - 1]
EndIf
Return \$peek
EndFunc

Func Isoperator(\$Operator)
Return StringInstr("+-*/^&<=>", \$Operator) <> 0 And StringLen(\$Operator) = 1
EndFunc

Func Precedence(\$Operator)
If Isoperator(\$Operator) Then
Switch \$Operator
case "^"
Return 4
case "*","/"
Return 3
case "+","-"
Return 2
case "&"
Return 1
case "<","=",">"
Return 0
EndSwitch
EndIf
EndFunc

;##################################################################################################

; (4 - -5) = (4|-|-|5) = (4|-|5|-)
;  input      tokens        rpn
Global \$calculate_this = ["4","-","5","-"]

Print(rpn(\$calculate_this))```

the negative number evaluation problem is still a big problem..

##### Share on other sites

Explain it.

Monkey's are, like, natures humans.

##### Share on other sites

Explain it.

the second problem?

well, in reverse polish notation 1|-|-|1 becomes 1|-|1|-

but my version of the rpn calculator can only deal with the '-' operator and does not know what to do with the second '-' (unary operator)..

hope I made my question more clear now

Edited by TheAutomator
##### Share on other sites

lol I have absolutely no idea what the pipe characters mean there at all, in either.

Monkey's are, like, natures humans.

##### Share on other sites

lol I have absolutely no idea what the pipe characters mean there at all, in either.

ok, sry

used "|" as a determiner for the tokens of the '\$calculate_this' variable to be more clear..

##### Share on other sites

Aren't you confusing two distinct operations? Substraction (dyadic) and sign_change (monadic).

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

##### Share on other sites

Aren't you confusing two distinct operations? Substraction (dyadic) and sign_change (monadic).

Yes, that's the problem.

I'm searching for a simple way to make the calculator function know which one is the subtraction operator and how to deal with

the rest of the negation signs..

##### Share on other sites

Differentiate between the regular sub - and some symbol evocating sign change, for instance ±

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

##### Share on other sites

Differentiate between the regular sub - and some symbol evocating sign change, for instance ±

How? can you maybe give me an example?

##### Share on other sites

I assume the unary (sign change) operator will either be the first instruction or else it will always be directly preceeded by another operator. If this is true, then you can test the type of operator using this rule. I don't know if I am correct - it's just a thought.

Edited by czardas
##### Share on other sites

This example seems to work also for negative numbers:

```Global \$__iStackElement = 0
Global \$oErrorHandler = ObjEvent("AutoIt.Error", "__Catch_COM_Errors")

ConsoleWrite(ReversePolishNotation("- * / 15 - 7 + 1 1 3 + 2 + 1 1") & @CRLF)
ConsoleWrite(ReversePolishNotation("/ 12 3") & @CRLF)
ConsoleWrite(ReversePolishNotation("/ 12 3-") & @CRLF)
ConsoleWrite(ReversePolishNotation("+ 1.25 2.25") & @CRLF)

Func ReversePolishNotation(\$sPolishNotation) ;coded by UEZ build 2014-09-07
If StringRegExp(\$sPolishNotation, "[^\d+|^\-|^\+|^\*|^\^|^\/|^\s|\.]", 0) Then Return SetError(1, 0, "") ;simple error handling only
Local \$oStack = Stack_Init()
Local \$aTokens = StringSplit(\$sPolishNotation, " ", 2)
If @error Then Return SetError(2, 0, "")
Local \$sToken, \$sOperand1, \$sOperand2
For \$sToken = UBound(\$aTokens) - 1 To 0 Step -1
Switch \$aTokens[\$sToken]
Case "+", "-", "/", "*", "^"
\$sOperand1 = Stack_Pop(\$oStack)
If StringRight(\$sOperand1, 1) = "-" Then \$sOperand1 = StringRegExpReplace(\$sOperand1, "(.+)-", "-\$1")
\$sOperand2 = Stack_Pop(\$oStack)
If StringRight(\$sOperand2, 1) = "-" Then \$sOperand2 = StringRegExpReplace(\$sOperand2, "(.+)-", "-\$1")
Stack_Push(Execute(\$sOperand1 & \$aTokens[\$sToken] & \$sOperand2), \$oStack)
Case Else
Stack_Push(\$aTokens[\$sToken], \$oStack)
EndSwitch
Next
Return Stack_Peek(\$oStack)
EndFunc   ;==>ReversePolishNotation

#Region Stack UDF
;stack (LIFO) implementation using ActiveXObject "Scripting.Dictionary" -> http://msdn.microsoft.com/en-us/library/x4k5wbx4(v=vs.84).aspx
;coded by UEZ (proof of concept version)
;~ #include-once

;function list:
;Stack_Clear
;Stack_Count
;Stack_Init
;Stack_IsEmpty
;Stack_Peek
;Stack_Pop
;Stack_PrintToConsole
;Stack_Push
;Stack_ToArray

;~ Global \$__iStackElement = 0
;~ Global \$oErrorHandler = ObjEvent("AutoIt.Error", "__Catch_COM_Errors")

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_Push
; Description ...: adds an element onto the stack
; Syntax ........: Stack_Push(\$element, \$obj)
; Parameters ....: \$element             - any kind of an element
;                  \$obj                 - must be the an object returned by Stack_Init()
; Return values .: True
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......:
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_Push(\$element, \$obj)
\$obj.Add(\$__iStackElement, \$element)
\$__iStackElement += 1
Return True
EndFunc   ;==>Stack_Push

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_Pop
; Description ...: returns the topmost element and removes it from the stack
; Syntax ........: Stack_Pop(\$obj)
; Parameters ....: \$obj                 - must be the an object returned by Stack_Init()
; Return values .: topmost element from the stack
;                  on error false and sets error to 1
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......: if stack is empty then error will be set to 1 and 0 returned
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_Pop(\$obj)
If Not \$__iStackElement Then Return SetError(1, 0, False)
Local \$return = \$obj.Item(\$__iStackElement - 1)
\$obj.Remove(\$__iStackElement - 1)
\$__iStackElement -= 1
Return \$return
EndFunc   ;==>Stack_Pop

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_Peek
; Description ...: returns the topmost element without removing it from the stack
; Syntax ........: Stack_Peek(\$obj)
; Parameters ....: \$obj                 - must be the an object returned by Stack_Init()
; Return values .: topmost element from the stack
;                  on error false and sets error to 1
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......: if stack is empty then error will be set to 1 and 0 returned
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_Peek(\$obj)
If Not \$__iStackElement Then Return SetError(1, 0, False)
Return \$obj.Item(\$__iStackElement - 1)
EndFunc   ;==>Stack_Peek

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_PrintToConsole
; Description ...: prints all stack elements to the console
; Syntax ........: Stack_PrintToConsole(\$obj)
; Parameters ....: \$obj                 - must be the an object returned by Stack_Init()
; Return values .: True
;                  on error false and sets error to 1
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......: if stack is empty then error will be set to 1 and 0 returned
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_PrintToConsole(\$obj)
If Not \$__iStackElement Then Return SetError(1, 0, False)
Local \$i
For \$i = \$__iStackElement - 1 To 0 Step -1
ConsoleWrite(\$obj.Item(\$i) & @CRLF)
Next
Return True
EndFunc   ;==>Stack_PrintToConsole

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_ToArray
; Description ...: returns an array with all stack elements
; Syntax ........: Stack_ToArray(\$obj[, \$bReverse = True])
; Parameters ....: \$obj                 - must be the an object returned by Stack_Init()
;                  \$bReverse            - [optional] a binary value. Default is True. If true topmost stack element is the 1st
;                                         entry in the array, if false then last element
; Return values .: array with all stack elements
;                  on error false and sets error to 1
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......: if stack is empty then error will be set to 1 and 0 returned
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_ToArray(\$obj, \$bReverse = True)
If Not \$__iStackElement Then Return SetError(1, 0, False)
Local \$a = \$obj.Items(), \$j = UBound(\$a) - 1
If Not \$j Then Return \$a
If Not \$bReverse Then Return \$a
Local \$i, \$aRevers[\$j + 1]
For \$i = 0 To \$j
\$aRevers[\$i] = \$a[\$j - \$i]
Next
Return \$aRevers
EndFunc   ;==>Stack_ToArray

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_Count
; Description ...: return the amount of stack elements
; Syntax ........: Stack_Count(\$obj)
; Parameters ....: \$obj                 - must be the an object returned by Stack_Init()
; Return values .: the amount of stack elements (an integer value)
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......:
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_Count(\$obj)
Return \$obj.Count()
EndFunc   ;==>Stack_Count

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_IsEmpty
; Description ...: checks whether stack is empty
; Syntax ........: Stack_IsEmpty(\$obj)
; Parameters ....: \$obj                 - must be the an object returned by Stack_Init()
; Return values .: True, if stack is empty, otherwise false
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......:
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_IsEmpty(\$obj)
Return \$obj.Count() = 0
EndFunc   ;==>Stack_IsEmpty

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_Clear
; Description ...: clears all stack elements
; Syntax ........: Stack_Clear(\$obj)
; Parameters ....: \$obj                 - must be the an object returned by Stack_Init()
; Return values .: None
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......:
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_Clear(\$obj)
\$obj.RemoveAll()
\$__iStackElement = 0
EndFunc   ;==>Stack_Clear

; #FUNCTION# ====================================================================================================================
; Name ..........: Stack_Init
; Description ...: initialize a stack object
; Syntax ........: Stack_Init()
; Parameters ....: None
; Return values .: an dictionary object
;                  on error false and sets error to 1
; Author ........: UEZ
; Version .......: 0.90 build 2014-04-14
; Remarks .......:
; Related .......: data types
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func Stack_Init()
Local \$oDictionary = ObjCreate('Scripting.Dictionary')
If @error Then Return SetError(1, 0, False)
Return \$oDictionary
EndFunc   ;==>Stack_Init

;internal functions
Func __Catch_COM_Errors()
ConsoleWrite( _
"A COM error has occured!" & @CRLF & @CRLF & _
"err.description is: " & @TAB & \$oErrorHandler.description & @CRLF & _
"err.windescription:" & @TAB & \$oErrorHandler & @CRLF & _
"err.number (hex) is: " & @TAB & Hex(\$oErrorHandler.number, 8) & @CRLF & _
"err.lastdllerror is: " & @TAB & \$oErrorHandler.lastdllerror & @CRLF & _
"err.scriptline is: " & @TAB & \$oErrorHandler.scriptline & @CRLF & _
"err.source is: " & @TAB & \$oErrorHandler.source & @CRLF & _
"err.helpfile is: " & @TAB & \$oErrorHandler.helpfile & @CRLF & _
"err.helpcontext is: " & @TAB & \$oErrorHandler.helpcontext & @CRLF _
)
EndFunc   ;==>__Catch_COM_Errors
#EndRegion Stack UDF```
Edit: added ^ operator.

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

##### Share on other sites

My take:

```#include <Array.au3>

Func Print(\$what, \$err = 0)
\$t = ''
if \$err <> 0 then \$t = 'ERROR!'
MsgBox(\$err, \$t, \$what)
EndFunc

Func Bye(\$iCause)
Local Const \$aReason = [ _
"Invalid input.", _
"The user has not input enough values in the expression.", _
"The user has input too many values in the expression." _
]
Print(\$aReason[\$iCause], 16)
Exit
EndFunc

Func RPN(\$aTokens)
If UBound(\$aTokens) < 1 Then Bye(0)
Local \$iToken = 0
While Ubound(\$aTokens) > 1 And \$iToken < UBound(\$aTokens)
If \$aTokens[\$iToken] = "±" Then        ; only one monadic operator
\$aTokens[\$iToken - 1] = -\$aTokens[\$iToken - 1]
_ArrayDelete(\$aTokens, \$iToken)
\$iToken -= 1
ElseIf StringInstr("+-*/^&<=>", \$aTokens[\$iToken]) Then
If \$iToken < 2 Then Bye(1)
Switch \$aTokens[\$iToken]        ; process dyadic operators
Case "+", "-", "*", "/", "^"
\$aTokens[\$iToken - 2] = Execute(Number(\$aTokens[\$iToken - 2]) & \$aTokens[\$iToken] & Number(\$aTokens[\$iToken - 1]))
Case Else
Bye(2)
EndSwitch
_ArrayDelete(\$aTokens, \$iToken)
_ArrayDelete(\$aTokens, \$iToken - 1)
\$iToken -= 2
Else                                ; must be a value
\$iToken += 1
EndIf
WEnd
Return \$aTokens[0]
EndFunc

;~ Func Precedence(\$Operator)
;~     If Isoperator(\$Operator) Then
;~         Switch \$Operator
;~             case "±"
;~                 Return 5
;~             case "^"
;~                 Return 4
;~             case "*","/"
;~                 Return 3
;~             case "+","-"
;~                 Return 2
;~             case "&"
;~                 Return 1
;~             case "<","=",">"
;~                 Return 0
;~         EndSwitch
;~     EndIf
;~ EndFunc

;##################################################################################################

; (4 - ±5) / 3.14 = 4|5|±|-|3.1415926|/
;      input              rpn
Global \$calculate_this = [4, 5, "±", "-", 3.1415926, "/"]

Print(rpn(\$calculate_this))```

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

##### Share on other sites

I was clearly wrong. Interesting examples!

##### Share on other sites
czardas,
no problem, thanks for the help

UEZ,
trying to figure out what you just did there,

1. first you check what the token is,
2. if it is a number:
3.     you push it to the stack,
4. if it is an operator:
5.     Operand1 = first value
6.         if the last char of Operand1 is a '-' then Operand1 = '-' & the value of Operand1 without the '-'
7.     Operand2 = second value
8.         if the last char of Operand2 is a '-' then Operand2 = '-' & the value of Operand2 without the '-'
9.         (tell me if i'm wrong here, i'm a noob if it comes to regex..)
10.     then let autoit evaluate(Operand1 & operator token & Operand2)
is this correct?
well, the shunting yard algorithm i made returns the tokens token by token, '3-' could never be a single token, to would rather be '3', '-'

jchd,
I never heard about this '±' operator before, i don't even know how to type it...
what i'm trying to find out is how to let my script know how to do '1 - -2'
so i don't want to use '±', want it to calculations based on a simple basic syntax with only '+','-','*','/' and '^'.
made a tokenization function that converts "1+2--3*5&"abc" to array["1","+","2","-","-","3","*","5","&",'"abc"'] and if
the current rpn calculator (after conversion to reverse polish notation) sees the extra minus it does not know what to do with it..
thanks for the help and your example, i didn't know you actually wanted to put that symbol into the algorithm.
Edited by TheAutomator
##### Share on other sites

That isn't going to work anyday, period.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

##### Share on other sites

That isn't going to work anyday, period.

'?do=embed' frameborder='0' data-embedContent>>

he did it with the ordinary '-' I think, but i'm still trying to figure out how at the moment..

## 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
• ### Recently Browsing   0 members

No registered users viewing this page.

• ### Similar Content

• it recomended to use the builten function
_DateDiff

hello autoit team
i made a simple function to help me get the difference between to date
i liked to share it with you
the paramatrs of this function
is firstdate and lastedate
the two params is as the following
year/month/day hours:minuts:seconds
here is the function

#include <date.au3> func _dateBetween(\$s_firstDate, \$s_lastDate = default) if not (StringRegExp(\$s_firstDate, "((\d{4})\/(\d{2})\/(\d{2})\s(\d{2})\:(\d{2})\:(\d{2}))", 0) = 1) then Return SetError(1, 0, 0) if \$s_lastDate = default then \$s_lastDate = @year & "/" & @mon & "/" & @mday & " " & @hour & ":" & @min & ":" & @sec if not (StringRegExp(\$s_lastDate, "((\d{4})\/(\d{2})\/(\d{2})\s(\d{2})\:(\d{2})\:(\d{2}))", 0) = 1) then Return SetError(2, 0, 0) local \$a_FirstSplitDate = StringSplit(StringRegExpReplace(\$s_firstDate, "((.*)\s(.*))", "\$2"), "/", 2) local \$a_FirstSplitTime = StringSplit(StringRegExpReplace(\$s_firstDate, "((.*)\s(.*))", "\$3"), ":", 2) local \$a_lastSplitDate = StringSplit(StringRegExpReplace(\$s_lastDate, "((.*)\s(.*))", "\$2"), "/", 2) local \$a_LastSplitTime = StringSplit(StringRegExpReplace(\$s_lastDate, "((.*)\s(.*))", "\$3"), ":", 2) local \$i_firstDateValue = _DateToDayValue(\$a_FirstSplitDate[0], \$a_FirstSplitDate[1], \$a_FirstSplitDate[2]) local \$i_LastDateValue = _DateToDayValue(\$a_LastSplitDate[0], \$a_LastSplitDate[1], \$a_LastSplitDate[2]) if \$i_firstDateValue > \$i_LastDateValue then Return SetError(3, 0, 0) local \$i_totalDays = \$i_LastDateValue-\$i_firstDateValue if not (\$i_totalDays = 0) then if \$a_FirstSplitTime[0] <= \$a_lastSplitTime[0] then \$i_totalDays += 1 \$a_lastSplitTime[0] -= \$a_FirstSplitTime[0] elseIf \$a_FirstSplitTime[0] > \$a_lastSplitTime[0] then if \$i_totalDays > 0 then \$i_totalDays -= 1 \$a_FirstSplitTime[0] -= \$a_lastSplitTime[0] endIf endIf endIf local \$i_totalYears = 0 if \$i_totalDays >= 365 then While \$i_totalDays >= 365 \$i_totalYears += 1 \$i_totalDays -= 365 Wend endIf local \$i_TotalMonths = 0 if \$i_totalDays >= 30 then While \$i_totalDays >= 30 \$i_totalMonths += 1 \$i_totalDays -= 30 Wend endIf local \$i_totalWeeks = 0 if \$i_totalDays >= 7 then While \$i_totalDays >= 7 \$i_totalWeeks += 1 \$i_totalDays -= 7 Wend endIf \$i_totalSeconds = (((\$a_FirstSplitTime[0]*60)*60)+(\$a_FirstSplitTime[1]*60)+(\$a_FirstSplitTime[2]))-(((\$a_lastSplitTime[0]*60)*60)+(\$a_lastSplitTime[1]*60)+(\$a_LastSplitTime[2])) local \$minus = "" if \$i_totalSeconds < 0 then \$minus = "-" \$i_totalSeconds = StringReplace(\$i_totalSeconds, "-", "") endIf local \$i_totalHours = 0 if \$i_totalSeconds >= 3600 then While \$i_totalSeconds >= 3600 \$i_totalHours += 1 \$i_totalSeconds -= 3600 Wend endIf local \$i_totalminuts = 0 if \$i_totalSeconds >= 60 then While \$i_totalSeconds >= 60 \$i_totalminuts += 1 \$i_totalSeconds -= 60 Wend endIf local \$a_arrayReturn[7] \$a_arrayReturn[0] = \$i_totalYears \$a_arrayReturn[1] = \$i_totalMonths \$a_arrayReturn[2] = \$i_totalWeeks \$a_arrayReturn[3] = \$i_totalDays \$a_arrayReturn[4] = \$minus & \$i_totalHours \$a_arrayReturn[5] = \$minus & \$i_totalminuts \$a_arrayReturn[6] = \$minus & \$i_totalSeconds return \$a_arrayReturn endFunc
here is an example

\$a_calc = _dateBetween("2015/02/12 23:00:05", "2030/02/12 23:25:50") msgBox(64, "result", StringFormat("the difference is : %i years and %i months and %i weeks and %i days and %i hours and %i minuts and %i seconds", \$a_calc[0], \$a_calc[1], \$a_calc[2], \$a_calc[3], \$a_calc[4], \$a_calc[5], \$a_calc[6]))
am waiting for your comments
with my greetings
• By Simpel
Hi,
I wondered why negative integers I wrote into registry (e.g. negative x-coordinates of a gui if using two monitors and the right one is the main one) wouldn't return right when reading. Now I know: it is saved as an unsigned integer (without algebraic sign). So here is a snippet that is changing unsigned to signed integer:
Global Const \$g_sRegKey = "HKEY_CURRENT_USER\Software\" & @ScriptName ; path to registry RegWrite(\$g_sRegKey, "Value", "REG_DWORD", -2147483647) ; write some negative integer into registry; -2147483647 highest possible negative integer , 2147483648 highest possible positive integer if talking of 32bit Local \$sValue = RegRead(\$g_sRegKey, "Value") ; read out registry ConsoleWrite("Value: " & \$sValue & @CRLF) ; show real value in console Local \$sResult = _SignedInteger(\$sValue) ; change to signed value ConsoleWrite("Result: " & \$sResult & @CRLF) ; and show it in console Func _SignedInteger(\$iUnsignedInteger) Local \$iSignedInteger If \$iUnsignedInteger > (2^31) Then ; then it means a negative integer \$iSignedInteger = \$iUnsignedInteger - (2^32) Else \$iSignedInteger = \$iUnsignedInteger EndIf Return \$iSignedInteger EndFunc It took me some time to find out the problem and so I hope I can help somebody with this.
Regards, Conrad
• By imitto
Hello all!
I use Autoit for a while, already made some automation for a TV station's master control room with it. I made a UDF to easily work with PAL timecode and time with milliseconds, convert, add or subtract them. Feel free to use it if you want something like this
#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Res_Description=PAL Timecode Calculator UDF #AutoIt3Wrapper_Res_LegalCopyright=horvath.imre@gmail.com #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** ; ; #FUNCTION# ; Name...........: _tcAdd ; Description....: Returns addition of two timecodes ; Syntax.........: _tcAdd(\$fTc1, fTc2 [, \$fFormat = "P"]) ; ; Parameters.....: \$fTc1 - First timecode in hh:mm:ss.ff format ; \$fTc2 - Second timecode in hh:mm:ss.ff format ; \$fFormat - Time base - "P" (default): PAL (25 fps) ; "M" : millisecond ; ; Return value...: Sum of the two timecode in the selected format Func _tcAdd(\$fTc1, \$fTc2, \$fFormat = "P", \$fHourFormat = 1) Local \$fMs1 = _tcToMs(\$fTc1) Local \$fMs2 = _tcToMs(\$fTc2) Local \$fSumMs = \$fMs1 + \$fMs2 Return _msToTc(\$fSumMs, \$fFormat, \$fHourFormat) EndFunc ; #FUNCTION# ; Name...........: _tcsSub ; Description....: Returns addition of two timecodes ; Syntax.........: _tcSub(\$fTc1, fTc2 [, \$fFormat = "P"]) ; ; Parameters.....: \$fTc1 - First timecode in hh:mm:ss.ff format ; \$fTc2 - Second timecode in hh:mm:ss.ff format ; \$fFormat - Time base - "P" (default): PAL (25 fps) ; "M" : millisecond ; ; Return value...: Subtract \$fTc2 from \$fTc1 in the source format Func _tcSub(\$fTc1, \$fTc2, \$fFormat = "P") Local \$fMs1 = _tcToMs(\$fTc1) Local \$fMs2 = _tcToMs(\$fTc2) Local \$fSumMs = \$fMs1 - \$fMs2 If \$fSumMs < 0 Then \$fSumMs = _tcToMs("24:00:00.00") - (\$fSumMs * -1) EndIf Return _msToTc(\$fSumMs, \$fFormat) EndFunc ; #FUNCTION# ; Name...........: _tcToMs ; Description....: Returns timecode converted to total milliseconds ; Syntax.........: _tcToMs(\$fTc) ; ; Parameters.....: \$fTc - Timecode in hh:mm:ss.ff or hh:mm:ss:xxx format, where xxx are milliseconds ; ; Return value...: Milliseconds as an integer value Func _tcToMs(\$fTc) Local \$fTemp = StringSplit(\$fTc, ":.") Local \$fChr = StringLen(\$fTemp[4]) Switch \$fChr Case 2 Return (\$fTemp[4] * 40) + (\$fTemp[3] * 1000) + (\$fTemp[2] * 60000) + (\$fTemp[1] * 3600000) Case 3 Return (\$fTemp[4]) + (\$fTemp[3] * 1000) + (\$fTemp[2] * 60000) + (\$fTemp[1] * 3600000) EndSwitch EndFunc ; #FUNCTION# ; Name...........: _msToTc ; Description....: Converts total milliseconds to timecode ; Syntax.........: _msToTc(\$fIn, \$fFormat = "P", \$fHourFormat = 1) ; ; Parameters.....: \$fIn - Time in milliseconds ; \$fFormat - Output format "P": PAL TC (default) ; "M": hh:mm:ss.xxx where xxx are milliseconds ; \$fHourFormat - Hour format "1": max. value is 23, then starts from 0 (default) ; "0": hours can be more then 23 ; ; Return value...: Timecode as string in the selected format Func _msToTc(\$fIn, \$fFormat = "P", \$fHourFormat = 1) Switch \$fFormat Case "P" Local \$fFr = StringFormat("%02i", (StringRight(\$fIn, 3) - Mod(StringRight(\$fIn, 3), 40)) / 40) Case "M" Local \$fFr = StringFormat("%03i", StringRight(\$fIn, 3)) EndSwitch \$fIn = StringTrimRight(\$fIn, 3) Local \$fSec = StringFormat("%02i", Mod(\$fIn, 60)) \$fIn -= \$fSec Local \$fMinTot = \$fIn / 60 Local \$fMin = StringFormat("%02i", Mod(\$fMinTot, 60)) \$fIn -= \$fMin*60 Local \$fHourTot = \$fIn / 60 / 60 Switch \$fHourFormat Case 1 \$fHour = StringFormat("%02i", Mod(\$fHourTot, 24)) Case 0 \$fHour = StringFormat("%02i", \$fHourTot) EndSwitch Return(\$fHour & ":" & \$fMin & ":" & \$fSec & "." & \$fFr) EndFunc ; #FUNCTION# ; Name...........: _tcFormatChange ; Description....: Toggle TC format ; Syntax.........: _tcFormatChange(\$fTc) ; ; Parameters.....: \$fTc - Timecode in hh:mm:ss.ff or hh:mm:ss:xxx format, where xxx are milliseconds ; ; Return value...: PAL timecode or time with milliseconds as string, depends on input Func _tcFormatChange(\$fTc) Local \$fTemp = StringSplit(\$fTc, ":.") Local \$fChr = StringLen(\$fTemp[4]) Switch \$fChr Case 2 Return \$fTemp[1]&":"&\$fTemp[2]&":"&\$fTemp[3]&"."&StringFormat("%03i", \$fTemp[4]*40) Case 3 Return \$fTemp[1]&":"&\$fTemp[2]&":"&\$fTemp[3]&"."&StringFormat("%02i", (\$fTemp[4]-Mod(\$fTemp[4], 40))/40) EndSwitch EndFunc And the example script:
#include<_PAL_TC_Calc.au3> \$palTC1 = "00:01:12.20" \$palTC2 = "23:59:50.02" \$msTC1 = "00:01:12.800" \$msTC2 = "23:59:50.120" MsgBox(0, "1", _tcAdd(\$palTC1, \$palTC2)); Adds \$palTC1 to \$palTC2, turns hour back to 0 after 23, returns PAL TC format MsgBox(0, "2", _tcAdd(\$palTC1, \$palTC2, "M")); Adds \$palTC1 to \$palTC2, turns hour back to 0 after 23, returns time with milliseconds format MsgBox(0, "3", _tcAdd(\$palTC1, \$palTC2, "M", 0)); Adds \$palTC1 to \$palTC2, hours can be infinite, returns time with milliseconds format MsgBox(0, "4", _tcAdd(\$msTC1, \$msTC2)); Adds \$palTC1 to \$palTC2, turns hour back to 0 after 23, returns PAL TC format MsgBox(0, "5", _tcAdd(\$msTC1, \$msTC2, "M")); Adds \$palTC1 to \$palTC2, turns hour back to 0 after 23, returns time with milliseconds format MsgBox(0, "6", _tcAdd(\$msTC1, \$msTC2, "M", 0)); Adds \$palTC1 to \$palTC2, hours can be infinite, returns time with milliseconds format MsgBox(0, "7", _tcSub(\$palTC2, \$palTC1)); Subtract \$palTC1 from \$palTC2, returns PAL TC format MsgBox(0, "8", _tcSub(\$palTC2, \$palTC1, "M")); Subtract \$palTC1 from \$palTC2, time with milliseconds format MsgBox(0, "9", _tcSub(\$msTC1, \$msTC2)); Subtract \$palTC1 from \$palTC2, returns PAL TC format - when hits zero, counts back from 24:00:00.00 MsgBox(0, "10", _tcSub(\$msTC1, \$msTC2, "M")); Subtract \$palTC1 from \$palTC2, time with milliseconds format - when hits zero, counts back from 24:00:00.000 MsgBox(0, "11", _tcFormatChange(\$palTC2)); Convert PAL TC to time with milliseconds and back MsgBox(0, "12", _tcFormatChange(\$msTC2)); Convert PAL TC to time with milliseconds and back
TC_CALC_example.au3
_PAL_TC_Calc.au3

• Hi dears
How are you?
I have a question, to you please.
How do I create an edit box for numbers only and does not accept letters? using autoit
greetings to all
I hope you help ME
Thanks to all in advance
• By UritOR
Hi all,
How do I allow an input control (GUICtrlCreateInput) to get only digits and dots?
\$ES_NUMBER - allows only digits, but I need to be able to type something like this only:   2.15.1598.1
Can you help me please?
×

• Wiki

• Back

• #### Beta

• Git
• FAQ
×
• Create New...