Jump to content

# a simple calculator function

## Recommended Posts

EDIT:27th Jan 2008

This was only intended as a 'mental' exercise to see how to do all this using recursion when I had some time to waste. It only reproduces what Execute can do much more simply and in only one line. I never fully tested this so I can't say how well it works. I hadn't expected anyone to copy it as the way to make a calculator. When I said below 'entirely in AutoIt' I meant using basic instructions to calculate a result without using Execute. At the time I even tried to make my own antilog function before I lost interest in the whole idea.

Original post follows-

There has been some interest in the online calculators but they all seem a bit restricted. Google for example doesn't know about Arcsin or Asin etc as far as I can see.

Anyway, I thought there aught to be an example of a calculator which is entirely in Autoit, and I didn't find anything so here is an attempt.

Not the most exciting script in the world and I'm already sick of it but it seems to work.

It takes a string like "(3*12.7^3.63/7)*cos(41.9)" and returns the answer.

```Const \$pi = 3.141592653589793, \$pifactor = \$pi/180;
Global \$stringtocalc,\$splitcalc,\$pp
#region front end for demo
While 1
\$string= InputBox('enter the calculation to make','allowed operators and functions' _
&  @LF  & ' *,  /, +, pi, sin(degrees), cos(degrees), tan(degrees), arcsin(degrees), ' _
& @CR & 'arccos(degrees), arctan(degrees), ^,  (,  ) ' _
& @CR & @CR & ' Eg ((45- 3^2.6)/17)*cos(23.7)',"","",450,200)
If \$string = '' Then Exit
\$string = StringStripWS(\$string,8)
If StringRight(\$string,1) = '=' Then
\$string = StringMid(\$string,1,StringLen(\$string)-1)
EndIf

MsgBox(0,\$string & ' = ',calculate(\$string))
;MsgBox(0,antilog(Log(\$String)),Exp(Log(\$string)))
WEnd
#endregion front end for demo

;rest of script is the calculator function
;return the clulcation result of  \$stringin
;very little error checking, just a sample to show a way to make a calculator
Func calculate(\$stringin)
\$stringin = StringUpper(\$stringin)
\$stringin = StringReplace(\$stringin,'^','**')
\$stringin = StringReplace(\$stringin,'#','+')

\$stringtocalc = \$stringin & '='
\$splitcalc = StringSplit(\$stringtocalc,"")
\$pp = 1

Return compute(0,0)

EndFunc

func compute(\$actual,\$rank);
Local  \$mtt,\$tem1,\$tem2,\$pnum2,\$bracketset,\$f1,\$f2,\$dum

\$tem1=0;
;\$tem2=0;
\$bracketset=0;

if (\$actual > 2) then \$actual = 2;

while(True)
\$pp += 1;
Switch \$splitcalc[\$pp-1]
Case ' '
;ignore

Case 'S'  ;sin?
ConsoleWrite('got the s for sin' &@CRLF)
If StringMid(\$stringtocalc,\$pp - 1,3) = "SIN" then

\$pp += 2

\$tem1 = sin(\$pifactor * compute(\$actual,3));
EndIf

Case 'T';tan?
If StringMid(\$stringtocalc,\$pp - 1,3) = "TAN" then

\$pp += 2
\$tem1 = Tan(\$pifactor * compute(\$actual,3));
EndIf
If \$pp < \$splitcalc[0] Then
while( \$splitcalc[\$pp] = '.') or StringIsDigit(\$splitcalc[\$pp])
\$pp += 1;
WEnd
EndIf

Case 'A'
If StringMid(\$stringtocalc,\$pp - 1,6) = "ARCTAN" then

\$pp += 5;
\$tem1 = atan(compute(\$actual,3))/\$pifactor;
elseif  StringMid(\$stringtocalc,\$pp - 1,6) = 'ARCSIN' then

\$pp += 4;
ConsoleWrite('at arcsin pp = ' & \$splitcalc[\$pp] & @CRLF)

\$mtt = compute(\$actual,3);
ConsoleWrite('\$mtt = ' & \$mtt & @CRLF)
\$tem1 = ASin(\$mtt)/\$pifactor;

elseif (StringMid(\$stringtocalc,\$pp - 1,6) = 'ARCCOS')  then

\$pp += 5
\$tem1 = ACos(compute(\$actual,3))/\$pifactor;
EndIf

If \$pp < \$splitcalc[0] Then
while( \$splitcalc[\$pp] = '.') or StringIsDigit(\$splitcalc[\$pp+1])
\$pp += 1; {get past the Add bit}
WEnd
EndIf

Case 'P';pi?
if (\$splitcalc[\$pp] = 'I') then \$tem1 = \$PI;
\$pp += 1;

Case 'C';cos?

if  StringMid(\$stringtocalc,\$pp - 1,3) = 'COS' then
\$pp += 2
\$tem1 = cos(\$pifactor * compute(\$actual,3));
EndIf
Case '('
\$bracketset = 1;
\$tem1 = compute(\$actual,0);
Case ')'
if (\$bracketset = 1) then
\$bracketset = 0
else
\$pp -= 1;
\$result = \$tem1;
Return \$result
EndIf
Case '/'
if (\$rank >= 2) then

\$pp -= 1;
\$result = \$tem1;
Return \$result

else

\$tem2 = compute(\$actual,2);
if (\$tem2 = 0) then

MsgBox(0,'Error','divide by 0!');
\$divzero = True;
\$result = 0;
Return \$result;
else
\$tem1 = \$tem1/\$tem2;
EndIf
EndIf
Case '*'

if \$splitcalc[\$pp] = '*' then
;exponent required
\$pp += 1;point to exp
ConsoleWrite('actual for power = ' & \$splitcalc[\$pp] & @CRLF)
If \$splitcalc[\$pp] = '-'  Then
\$pp += 1
\$tem2 = -compute(\$actual,4)
ElseIf \$splitcalc[\$pp] = '+'  Then
\$pp += 1
\$tem2 = compute(\$actual,4)
Else
\$tem2 = compute(\$actual,4);
EndIf
\$tem1 = Power(\$tem1,\$tem2);
;Return \$tem1
else

if (\$rank >= 3) then
\$pp -= 1;
\$result = \$tem1;
Return \$result;
else

\$mtt = compute(\$actual,3);
\$tem1 = \$tem1 * \$mtt;
EndIf;
EndIf;

Case '+'
if (\$rank >= 1) then

\$pp -= 1;
\$result = \$tem1;
Return \$result
else
\$tem1 = \$tem1 + compute(\$actual,1);
EndIf;

Case '-';
consolewrite('rank= ' & \$rank & '\$tem =' &  \$tem1 & @CRLF)
if (\$rank >= 1) then
\$pp -= 1
\$result = - \$tem1;
Return \$result
else

\$tem1 = \$tem1 - compute(\$actual,1);
EndIf;
Case '=' ;{CR LF NULL}
\$pp -= 1;{set back to end of line or compute will go crashing through the comments}
\$result = \$tem1;
if (\$bracketset = 1)then
MsgBox(0,'ERROR','Unmatched brackets')
EndIf;
Return \$result
Case  '0' To '9';
\$pp -= 1;
\$pnum2 = \$pp;
while( \$splitcalc[\$pp] = '.') or StringIsDigit(\$splitcalc[\$pp])
\$pp += 1;
WEnd
\$tem1 = StringMid(\$stringtocalc,\$pnum2,\$pp-\$pnum2)
Case '.' ;
\$pp -= 1;
\$pnum2 = \$pp;
while( \$splitcalc[\$pp] = '.') or StringIsDigit(\$splitcalc[\$pp])
\$pp += 1;
WEnd
\$tem1 = StringMid(\$stringtocalc,\$pnum2,\$pp-\$pnum2)

Case ',';this bit doesn't work yet
;\$pp -= 1;
\$result = \$tem1;
Return \$result

EndSwitch;
wend;
#region

#endregion

EndFunc;

Func Max(\$a,\$B)
ConsoleWrite('a,b = ' & \$a & ', ' & \$b & @CRLF)
If \$a > \$b Then Return \$a
Return \$b
EndFunc

Func Min(\$a,\$B)
ConsoleWrite('a,b = ' & \$a & ', ' & \$b & @CRLF)
If \$a < \$b Then Return \$a
Return \$b
EndFunc

Func power(\$a,\$B)
ConsoleWrite('a,b = ' & \$a & ', ' & \$b &@CRLF)
;returns \$a to the power of \$b
If \$a < 1 Then
\$sign = -1
Else
\$sign = 1
EndIf

If \$b = 0 Then Return \$sign

If \$b < 0 Then
Return \$sign /Exp(Log(\$a)*\$b*-1)
Else
Return \$sign * Exp(Log(\$a)*\$B)
EndIf

EndFunc```

EDIT: replaced experimental antilog function with exp. Removed Max & Min which didn't work, a some improvements.

Edited by martin
Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
##### Share on other sites

Well... I'd like to say this will come into use, great work.

Edited by mrRevoked
Don't bother, It's inside your monitor!------GUISetOnEvent should behave more like HotKeySet()
##### Share on other sites

This is nice because this can be used in other languages as well.. I mean AutoIt has Execute() but this is AutoIt-specific. Nice and thanks!

##### Share on other sites

Google for example doesn't know about Arcsin or Asin etc as far as I can see.

go to google and type "asin(1)="

You are correct in that it will not evaluate it if you just enter "asin(1)" but it forces it to calculate if you add a "=" on the end.

## 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.

×

• Wiki

• Back

• #### Beta

• Git
• FAQ
• Our Picks
×
• Create New...