#!/usr/bin/env python ##Purpose of this calculator is to make solving and checking more ##simple and accurate. ##The TKinter is here to show us a calculator that can be used when ##your calculator has a problem or is missing or lost. ##The trail in the back of the calculator has all the previous ##operations the user has done, showing off all of the values and ##steps. ##Here is the order of operations from strongest (top) to weakest (bottom): ## nCr, nPr ## x^y, root ## *, / ## +, -, mod, and, or, xor, lsh, rsh ##Note that this program /should/ work against a DOS window! ##Created by Nicholas McConnell in 2010 from random import * # To work the [Rand] button, we need to import this. from math import * # This has most of the scientific operations. from Tkinter import * # By using this it is possible to layout in Tkinter root = Tk() root.title('Calculator With Trail') txtContents = StringVar() intInv = IntVar() intInv.set(0) intHyp = IntVar() intHyp.set(0) parCapt = StringVar() parCapt.set('') memCapt = StringVar() memCapt.set('') operation = [] for i in xrange(26): # 0-25 levels of parentheses operation.append([]) # This gets us [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] def stringOut(ls): """Return the same list with all empty strings removed.""" return [x for x in ls if x] par = 0 # Number of open parenthesis levels memory = 0 # Number stored in memory stiffen = 1 # Does the calculator want to clear the current number when a new one is entered? ##The following functions are defined because they are not yet attributes made in the math module here in Python 2-5-1. ##They have underscores because them without underscores will be read against Python 2-6-1. ##For example, atanh(0.1) would be evaluated here as . def __asinh__(x): # Area hyperbolic sine of x. x = float(x) return log(x+sqrt(x*x+1)) def __acosh__(x): # Area hyperbolic cosine of x. x = float(x) return log(x+sqrt(x*x-1)) def __atanh__(x): # Area hyperbolic tangent of x. x = float(x) return log((1+x)/(1-x))/2 def Fact(x): # Return x!. # nCr = (n!)/(r!*(n-r)!), nPr = (n!)/((n-r)!) assert x >= 0 assert isinstance(x, int) f = 1 for i in xrange(1, x + 1): f *= i return f def actRand(): # Input any random decimal (to 16 places) greater than or equal to 0 and less than 1. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact R = randrange(0, 10000000000000000L)/(1.0e+16) txtContents.set(str(R)) print ' rand %s' % R stiffen = 1 def actPi(): # Input value of pi. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact txtContents.set(str(pi)) print ' pi %s' % pi stiffen = 1 def actFact(): # Input factorial of displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if float(eval(txtContents.get())) >= 0.0: txtContents.set(str(float(Fact(int(eval(txtContents.get())))))) print ' x! %s' % txtContents.get() else: print ' (Negative arg in x!)' stiffen = 1 def actComb(): # Enter nCr into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' nCr' operation[par].append(txtContents.get()) operation[par].append('nCr') stiffen = 1 def actPerm(): # Enter nPr into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' nPr' operation[par].append(txtContents.get()) operation[par].append('nPr') stiffen = 1 def actRec(): # Input reciprocal of displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if float(eval(txtContents.get())) != 0.0: txtContents.set(str(1.0/float(eval(txtContents.get())))) print ' 1/x %s' % txtContents.get() else: print ' (Division By Zero in 1/x)' stiffen = 1 def actSqr(): # If Inv is checked, input square root of displayed number. # Otherwise, input square of displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): if float(eval(txtContents.get())) >= 0.0: txtContents.set(str(float(sqrt(eval(txtContents.get()))))) print ' sqrt %s' % txtContents.get() else: print ' (Out of Function Domain in sqrt)' else: txtContents.set(str(float(eval(txtContents.get())**2))) print ' x^2 %s' % txtContents.get() intInv.set(0) stiffen = 1 def actCube(): # If Inv is checked, input cube root of displayed number. # Otherwise, input cube of displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): if float(eval(txtContents.get())) >= 0.0: txtContents.set(str(float(eval(txtContents.get())**(1.0/3.0)))) print ' curt %s' % txtContents.get() else: print ' (Out of Function Domain in curt)' else: txtContents.set(str(float(eval(txtContents.get())**3))) print ' x^3 %s' % txtContents.get() intInv.set(0) stiffen = 1 def actPow(): # If Inv is checked, enter root into function. # Otherwise, enter x^y into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): print ' root' operation[par].append(txtContents.get()) operation[par].append('root') else: print ' x^y' operation[par].append(txtContents.get()) operation[par].append('x^y') intInv.set(0) stiffen = 1 def actSin(): # If Inv is checked: # If Hyp is checked, input area hyperbolic sine of displayed number. # Otherwise, input arc sine of displayed number. # Otherwise: # If Hyp is checked, input hyperbolic sine of displayed number. # Otherwise, input sine of displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): if intHyp.get(): txtContents.set(str(float(__asinh__(eval(txtContents.get()))))) print ' asinh %s' % txtContents.get() else: if float(eval(txtContents.get())) <= 1.0 and float(eval(txtContents.get())) >= -1.0: if angGroup.get() == 'Deg': txtContents.set(str(float(asin(eval(txtContents.get()))/pi*180))) print '(Deg) asin %s' % txtContents.get() elif angGroup.get() == 'Rad': txtContents.set(str(float(asin(eval(txtContents.get()))))) print '(Rad) asin %s' % txtContents.get() else: txtContents.set(str(float(asin(eval(txtContents.get()))/pi*200))) print '(Grad) asin %s' % txtContents.get() else: print ' (Out of Function Domain in asin)' else: if intHyp.get(): txtContents.set(str(float(sinh(eval(txtContents.get()))))) print ' sinh %s' % txtContents.get() else: if angGroup.get() == 'Deg': txtContents.set(str(float(sin(eval(txtContents.get())*pi/180)))) print '(Deg) sin %s' % txtContents.get() elif angGroup.get() == 'Rad': txtContents.set(str(float(sin(eval(txtContents.get()))))) print '(Rad) sin %s' % txtContents.get() else: txtContents.set(str(float(sin(eval(txtContents.get())*pi/200)))) print '(Grad) sin %s' % txtContents.get() intInv.set(0) intHyp.set(0) stiffen = 1 def actCos(): # If Inv is checked: # If Hyp is checked, input area hyperbolic cosine of displayed number. # Otherwise, input arc cosine of displayed number. # Otherwise: # If Hyp is checked, input hyperbolic cosine of displayed number. # Otherwise, input cosine of displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): if intHyp.get(): if float(eval(txtContents.get())) >= 1.0: txtContents.set(str(float(__acosh__(eval(txtContents.get()))))) print ' acosh %s' % txtContents.get() else: print ' (Out of Function Domain in acosh)' else: if float(eval(txtContents.get())) <= 1.0 and float(eval(txtContents.get())) >= -1.0: if angGroup.get() == 'Deg': txtContents.set(str(float(acos(eval(txtContents.get()))/pi*180))) print '(Deg) acos %s' % txtContents.get() elif angGroup.get() == 'Rad': txtContents.set(str(float(acos(eval(txtContents.get()))))) print '(Rad) acos %s' % txtContents.get() else: txtContents.set(str(float(acos(eval(txtContents.get()))/pi*200))) print '(Grad) acos %s' % txtContents.get() else: print ' (Out of Function Domain in acos)' else: if intHyp.get(): txtContents.set(str(float(cosh(eval(txtContents.get()))))) print ' cosh %s' % txtContents.get() else: if angGroup.get() == 'Deg': txtContents.set(str(float(cos(eval(txtContents.get())*pi/180)))) print '(Deg) cos %s' % txtContents.get() elif angGroup.get() == 'Rad': txtContents.set(str(float(cos(eval(txtContents.get()))))) print '(Rad) cos %s' % txtContents.get() else: txtContents.set(str(float(cos(eval(txtContents.get())*pi/200)))) print '(Grad) cos %s' % txtContents.get() intInv.set(0) intHyp.set(0) stiffen = 1 def actTan(): # If Inv is checked: # If Hyp is checked, input area hyperbolic tangent of displayed number. # Otherwise, input arc tangent of displayed number. # Otherwise: # If Hyp is checked, input hyperbolic tangent of displayed number. # Otherwise, input tangent of displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): if intHyp.get(): if float(eval(txtContents.get())) < 1.0 and float(eval(txtContents.get())) > -1.0: txtContents.set(str(float(__atanh__(eval(txtContents.get()))))) print ' atanh %s' % txtContents.get() else: print ' (Out of Function Domain in atanh)' else: if angGroup.get() == 'Deg': txtContents.set(str(float(atan(eval(txtContents.get()))/pi*180))) print '(Deg) atan %s' % txtContents.get() elif angGroup.get() == 'Rad': txtContents.set(str(float(atan(eval(txtContents.get()))))) print '(Rad) atan %s' % txtContents.get() else: txtContents.set(str(float(atan(eval(txtContents.get()))/pi*200))) print '(Grad) atan %s' % txtContents.get() else: if intHyp.get(): txtContents.set(str(float(tanh(eval(txtContents.get()))))) print ' tanh %s' % txtContents.get() else: if angGroup.get() == 'Deg': if (float(eval(txtContents.get()))-90.0)/180.0 == float(int((float(eval(txtContents.get()))-90.0)/180.0)): print ' (Out of Function Domain in tan)' else: txtContents.set(str(float(tan(eval(txtContents.get())*pi/180)))) print '(Deg) tan %s' % txtContents.get() elif angGroup.get() == 'Rad': if (float(eval(txtContents.get()))-pi/2)/pi == float(int((float(eval(txtContents.get()))-pi/2)/pi)): print ' (Out of Function Domain in tan)' else: txtContents.set(str(float(tan(eval(txtContents.get()))))) print '(Rad) tan %s' % txtContents.get() else: if (float(eval(txtContents.get()))-100.0)/200.0 == float(int((float(eval(txtContents.get()))-100.0)/200.0)): print ' (Out of Function Domain in tan)' else: txtContents.set(str(float(tan(eval(txtContents.get())*pi/200)))) print '(Grad) tan %s' % txtContents.get() intInv.set(0) intHyp.set(0) stiffen = 1 def actExp(): # Allow user to enter a scientific notation exponent. Best trial if 1 <= mantissa < 10. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact # Is there already an exponent? # See if adding e+0 and taking the eval jumps to the exception. if stiffen == 0: try: trial = eval('%se+0' % txtContents.get()) txtContents.set('%se+0' % txtContents.get()) except Exception, exponent: print ' (Incorrect place to put exponent)' else: print ' (Displayed number is read-only)' def actDms(): # If Inv is checked, convert from degrees-minutes-seconds to decimal degrees. # Otherwise, convert from decimal degrees to degrees-minutes-seconds. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): degrees = int(eval(txtContents.get())) minutes = int((eval(txtContents.get()) - int(eval(txtContents.get()))) * 100) seconds = (eval(txtContents.get()) * 100 - int(eval(txtContents.get()) * 100)) * 100 txtContents.set(str(float(degrees + minutes / 60.0 + seconds / 3600.0))) print ' dms ==> dd %s' % txtContents.get() else: degrees = int(eval(txtContents.get())) minutes = int((eval(txtContents.get()) - int(eval(txtContents.get()))) * 60) seconds = (eval(txtContents.get()) * 60 - int(eval(txtContents.get()) * 60)) * 60 txtContents.set(str(float(degrees + minutes / 100.0 + seconds / 10000.0))) print ' dd ==> dms %s' % txtContents.get() intInv.set(0) stiffen = 1 def actLeftP(): # Open a new layer of parentheses. Do not allow more than 25 layers. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if par < 25: print ' ( ...' par += 1 txtContents.set('0') stiffen = 1 parCapt.set('PAR = %d' % par) else: print ' (Too many open levels of parentheses)' def actRightP(): # Close current innermost layer of parentheses. # On the other hand, use the order of operations to solve for the result of the expression grouped by this layer. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if par > 0: operation[par].append(txtContents.get()) if stiffen == 0: print ' %s' % txtContents.get() if len(operation[par]) > 1: for i in xrange(1, len(operation[par]), 2): if operation[par][i] == 'nCr': if 0 <= int(eval(operation[par][i+1])) and int(eval(operation[par][i+1])) <= int(eval(operation[par][i-1])): operation[par][i+1] = str(float(Fact(int(eval(operation[par][i-1]))))/float(Fact(int(eval(operation[par][i+1])))*Fact(int(eval(operation[par][i-1]))-int(eval(operation[par][i+1]))))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Out of Function Domain in nCr)' elif operation[par][i] == 'nPr': if 0 <= int(eval(operation[par][i+1])) and int(eval(operation[par][i+1])) <= int(eval(operation[par][i-1])): operation[par][i+1] = str(float(Fact(int(eval(operation[par][i-1]))))/float(Fact(int(eval(operation[par][i-1]))-int(eval(operation[par][i+1]))))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Out of Function Domain in nPr)' operation[par] = stringOut(operation[par]) if len(operation[par]) > 1: for i in xrange(1, len(operation[par]), 2): if operation[par][i] == 'x^y': if float(eval(operation[par][i-1])) == 0.0 and float(eval(operation[par][i+1])) < 0.0: print ' (Out of Function Domain in x^y)' elif float(eval(operation[par][i-1])) < 0.0 and float(eval(operation[par][i+1])) > float(int(eval(operation[par][i+1]))): print ' (Out of Function Domain in x^y)' else: operation[par][i+1] = str(float(eval(operation[par][i-1]))**float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'root': if float(eval(operation[par][i+1])) != 0.0: if float(eval(operation[par][i-1])) == 0.0 and float(eval(operation[par][i+1])) < 0.0: print ' (Out of Function Domain in root)' elif float(eval(operation[par][i-1])) < 0.0 and 1.0/float(eval(operation[par][i+1])) > float(int(1.0/float(eval(operation[par][i+1])))): print ' (Out of Function Domain in root)' else: operation[par][i+1] = str(float(eval(operation[par][i-1]))**(1.0/float(eval(operation[par][i+1])))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Division by Zero in root)' operation[par] = stringOut(operation[par]) if len(operation[par]) > 1: for i in xrange(1, len(operation[par]), 2): if operation[par][i] == '*': operation[par][i+1] = str(float(eval(operation[par][i-1]))*float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == '/': if float(eval(operation[par][i+1])) != 0.0: operation[par][i+1] = str(float(eval(operation[par][i-1]))/float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Division by Zero in /)' operation[par] = stringOut(operation[par]) if len(operation[par]) > 1: for i in xrange(1, len(operation[par]), 2): if operation[par][i] == '+': operation[par][i+1] = str(float(eval(operation[par][i-1]))+float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == '-': operation[par][i+1] = str(float(eval(operation[par][i-1]))-float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Mod': if float(eval(operation[par][i+1])) != 0.0: operation[par][i+1] = str(float(eval(operation[par][i-1]))%float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Modulo Zero in Mod)' elif operation[par][i] == 'And': operation[par][i+1] = str(int(eval(operation[par][i-1]))&int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Or': operation[par][i+1] = str(int(eval(operation[par][i-1]))|int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Xor': operation[par][i+1] = str(int(eval(operation[par][i-1]))^int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Lsh': operation[par][i+1] = str(float(eval(operation[par][i-1]))*2**int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Rsh': operation[par][i+1] = str(float(eval(operation[par][i-1]))/2**int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' operation[par] = stringOut(operation[par]) print ' ) = %s' % float(eval(operation[par][0])) txtContents.set(str(float(eval(operation[par][0])))) operation[par] = [] par -= 1 stiffen = 1 if par > 0: parCapt.set('PAR = %d' % par) else: parCapt.set('') else: print ' (No open levels of parentheses to close)' def actLn(): # If Inv is checked, input the natural exponential function of the displayed number. # Otherwise, input the natural logarithm of the displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): txtContents.set(str(float(exp(eval(txtContents.get()))))) print ' e^x %s' % txtContents.get() else: if float(eval(txtContents.get())) > 0.0: txtContents.set(str(float(log(eval(txtContents.get()))))) print ' ln %s' % txtContents.get() else: print ' (Out of Function Domain in ln)' intInv.set(0) stiffen = 1 def actLog(): # If Inv is checked, input the common exponential function of the displayed number. # Otherwise, input the common logarithm of the displayed number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): txtContents.set(str(float(10**eval(txtContents.get())))) print ' 10^x %s' % txtContents.get() else: if float(eval(txtContents.get())) > 0.0: txtContents.set(str(float(log10(eval(txtContents.get()))))) print ' log %s' % txtContents.get() else: print ' (Out of Function Domain in log)' intInv.set(0) stiffen = 1 def actMod(): # Enter modulo into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' Mod' operation[par].append(txtContents.get()) operation[par].append('Mod') stiffen = 1 def actMC(): # Clear any number stored in memory. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact memory = 0 memCapt.set('') print ' (Memory cleared)' stiffen = 1 def actMR(): # Input number stored in memory. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact txtContents.set(str(memory)) print ' memory %s' % txtContents.get() stiffen = 1 def actMAdd(): # Add displayed number to memory. Do not display the sum of these numbers. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact memory += eval(txtContents.get()) print ' add memory: %s' % txtContents.get() if float(memory) != 0.0: memCapt.set('MEMORY') else: memCapt.set('') stiffen = 1 def actMSub(): # Subtract displayed number from memory. Do not display the difference of these numbers. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact memory -= eval(txtContents.get()) print ' sub memory: %s' % txtContents.get() if float(memory) != 0.0: memCapt.set('MEMORY') else: memCapt.set('') stiffen = 1 def actPosNeg(): # Change the sign of the displayed number. Special case for a scientific notation # exponent that the user is entering, and we must change the sign of the exponent. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1: txtContents.set(str(-float(eval(txtContents.get())))) print ' +/- %s' % txtContents.get() else: try: trial = eval('%se+0' % txtContents.get()) if txtContents.get()[0] == '-': txtContents.set(txtContents.get()[1:len(txtContents.get())]) else: txtContents.set('-%s' % txtContents.get()) except Exception, exponent: i = 0 for t in xrange(0, len(txtContents.get())): if txtContents.get()[t] == 'e': i = t if txtContents.get()[i+1] == '-': txtContents.set('%s+%s' % (txtContents.get()[0:i+1], txtContents.get()[i+2:len(txtContents.get())])) else: txtContents.set('%s-%s' % (txtContents.get()[0:i+1], txtContents.get()[i+2:len(txtContents.get())])) def actAnd(): # Enter bitwise AND into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' And' operation[par].append(txtContents.get()) operation[par].append('And') stiffen = 1 def actNot(): # Input bitwise NOT of displayed number. This operation depends on a bitrange, # and we must wrap around to the negative side where the answer is indepent of the bitrange. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() txtContents.set(str(float(-1-int(eval(txtContents.get()))))) print ' Not %s' % txtContents.get() stiffen = 1 def act7(): # Enter digit 7. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s7' % txtContents.get()) def act8(): # Enter digit 8. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s8' % txtContents.get()) def act9(): # Enter digit 9. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s9' % txtContents.get()) def actDiv(): # Enter division into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' /' operation[par].append(txtContents.get()) operation[par].append('/') stiffen = 1 def actOr(): # Enter bitwise inclusive OR into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' Or' operation[par].append(txtContents.get()) operation[par].append('Or') stiffen = 1 def actInt(): # If Inv is checked, input the decimal portion of the displayed number. # Otherwise, TRUNCATE the decimal portion of the displayed number: # If positive, get down to the greatest integer less than or equal to the number. # If negative, get up to the least integer greater than or equal to the number. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): txtContents.set(str(float(eval(txtContents.get()))-int(eval(txtContents.get())))) print ' Frac %s' % txtContents.get() else: txtContents.set(str(int(eval(txtContents.get())))) print ' Int %s' % txtContents.get() intInv.set(0) stiffen = 1 def act4(): # Enter digit 4. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s4' % txtContents.get()) def act5(): # Enter digit 5. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s5' % txtContents.get()) def act6(): # Enter digit 6. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s6' % txtContents.get()) def actMult(): # Enter multiplication into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' *' operation[par].append(txtContents.get()) operation[par].append('*') stiffen = 1 def actXor(): # Enter bitwise exclusive OR into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' Xor' operation[par].append(txtContents.get()) operation[par].append('Xor') stiffen = 1 def actC(): # Clear the displayed number only. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact txtContents.set('0') if stiffen == 1: print ' (Display cleared)' stiffen = 1 def act1(): # Enter digit 1. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s1' % txtContents.get()) def act2(): # Enter digit 2. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s2' % txtContents.get()) def act3(): # Enter digit 3. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s3' % txtContents.get()) def actSub(): # Enter subtraction into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' -' operation[par].append(txtContents.get()) operation[par].append('-') stiffen = 1 def actLsh(): # If Inv is checked, enter bitwise right shift into function. # Otherwise, enter bitwise left shift into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() if intInv.get(): print ' Rsh' operation[par].append(txtContents.get()) operation[par].append('Rsh') else: print ' Lsh' operation[par].append(txtContents.get()) operation[par].append('Lsh') intInv.set(0) stiffen = 1 def actAC(): # If Inv is checked, exit the calculator. # (This is like turning off a real hand-held calculator. # This AC button could be the on button, labeled ON/AC.) # Otherwise, clear the entire operation. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if intInv.get(): print '======================================OFF======================================' quit() else: print '====================================CLEARED====================================' par = 0 parCapt.set('') txtContents.set('0') operation = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []] stiffen = 1 def act0(): # Enter digit 0. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 1 or txtContents.get() == '0': txtContents.set('') stiffen = 0 if len(txtContents.get()) >= 3: if txtContents.get()[-3:len(txtContents.get())] == 'e+0' or txtContents.get()[-3:len(txtContents.get())] == 'e-0': txtContents.set(txtContents.get()[0:-1]) txtContents.set('%s0' % txtContents.get()) def actDec(): # Enter a decimal point. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact # Do not want to be picky alright. Only allow a decimal point if Python takes one. if stiffen == 1: txtContents.set('0.') stiffen = 0 else: try: trial = eval('%s.0' % txtContents.get()) txtContents.set('%s.' % txtContents.get()) except Exception, note: print ' (Incorrect place to put decimal point)' def actEq(): # Use order of operations to solve for the result of the expression. # This button does not work if there are any open layers of parentheses. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if par == 0: operation[par].append(txtContents.get()) if stiffen == 0: print ' %s' % txtContents.get() if len(operation[par]) > 1: for i in xrange(1, len(operation[par]), 2): if operation[par][i] == 'nCr': if 0 <= int(eval(operation[par][i+1])) and int(eval(operation[par][i+1])) <= int(eval(operation[par][i-1])): operation[par][i+1] = str(float(Fact(int(eval(operation[par][i-1]))))/float(Fact(int(eval(operation[par][i+1])))*Fact(int(eval(operation[par][i-1]))-int(eval(operation[par][i+1]))))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Out of Function Domain in nCr)' elif operation[par][i] == 'nPr': if 0 <= int(eval(operation[par][i+1])) and int(eval(operation[par][i+1])) <= int(eval(operation[par][i-1])): operation[par][i+1] = str(float(Fact(int(eval(operation[par][i-1]))))/float(Fact(int(eval(operation[par][i-1]))-int(eval(operation[par][i+1]))))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Out of Function Domain in nPr)' operation[par] = stringOut(operation[par]) if len(operation[par]) > 1: for i in xrange(1, len(operation[par]), 2): if operation[par][i] == 'x^y': if float(eval(operation[par][i-1])) == 0.0 and float(eval(operation[par][i+1])) < 0.0: print ' (Out of Function Domain in x^y)' elif float(eval(operation[par][i-1])) < 0.0 and float(eval(operation[par][i+1])) > float(int(eval(operation[par][i+1]))): print ' (Out of Function Domain in x^y)' else: operation[par][i+1] = str(float(eval(operation[par][i-1]))**float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'root': if float(eval(operation[par][i+1])) != 0.0: if float(eval(operation[par][i-1])) == 0.0 and float(eval(operation[par][i+1])) < 0.0: print ' (Out of Function Domain in root)' elif float(eval(operation[par][i-1])) < 0.0 and 1.0/float(eval(operation[par][i+1])) > float(int(1.0/float(eval(operation[par][i+1])))): print ' (Out of Function Domain in root)' else: operation[par][i+1] = str(float(eval(operation[par][i-1]))**(1.0/float(eval(operation[par][i+1])))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Division by Zero in root)' operation[par] = stringOut(operation[par]) if len(operation[par]) > 1: for i in xrange(1, len(operation[par]), 2): if operation[par][i] == '*': operation[par][i+1] = str(float(eval(operation[par][i-1]))*float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == '/': if float(eval(operation[par][i+1])) != 0.0: operation[par][i+1] = str(float(eval(operation[par][i-1]))/float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Division by Zero in /)' operation[par] = stringOut(operation[par]) if len(operation[par]) > 1: for i in xrange(1, len(operation[par]), 2): if operation[par][i] == '+': operation[par][i+1] = str(float(eval(operation[par][i-1]))+float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == '-': operation[par][i+1] = str(float(eval(operation[par][i-1]))-float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Mod': if float(eval(operation[par][i+1])) != 0.0: operation[par][i+1] = str(float(eval(operation[par][i-1]))%float(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' else: print ' (Modulo Zero in Mod)' elif operation[par][i] == 'And': operation[par][i+1] = str(int(eval(operation[par][i-1]))&int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Or': operation[par][i+1] = str(int(eval(operation[par][i-1]))|int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Xor': operation[par][i+1] = str(int(eval(operation[par][i-1]))^int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Lsh': operation[par][i+1] = str(float(eval(operation[par][i-1]))*2**int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' elif operation[par][i] == 'Rsh': operation[par][i+1] = str(float(eval(operation[par][i-1]))/2**int(eval(operation[par][i+1]))) operation[par][i] = '' operation[par][i-1] = '' operation[par] = stringOut(operation[par]) print ' = %s' % float(eval(operation[par][0])) txtContents.set(str(float(eval(operation[par][0])))) operation[par] = [] stiffen = 1 else: if par != 1: plural = 's' else: plural = '' print ' (%s open level%s of parentheses)' % (par, plural) def actAdd(): # Enter addition into function. global txtContents, operation, stiffen, intInv, intHyp, angGroup, __asinh__, __acosh__, __atanh__, parCapt, memCapt, par, memory, Fact if stiffen == 0: print ' %s' % txtContents.get() print ' +' operation[par].append(txtContents.get()) operation[par].append('+') stiffen = 1 ##This is the heading of the trail of the calculator, which summarizes the ##entire operations you enter in. For example, if you first submit the ##calculation 81 ^ -(3/4), then press AC, and then submit the calculation ##sqrt(4/pi), the trail would look like this: # Python Calculator Trail # ====================================CLEARED==================================== # 81 # x^y # ( ... # 3 # / # 4 # ) = 0.75 # +/- -0.75 # = 0.037037037037 # ====================================CLEARED==================================== # ( ... # 4 # / # pi 3.14159265359 # ) = 1.27323954474 # sqrt 1.1283791671 print 'Python Calculator Trail' print '====================================CLEARED====================================' chkInv = Checkbutton(root, text='Inv', width=2, variable=intInv).grid(row=2, column=0) # Inverse Function chkHyp = Checkbutton(root, text='Hyp', width=2, variable=intHyp).grid(row=2, column=1) # Hyperbolic Function # Angle Unit (Trigonometric Input) angGroup = StringVar() angGroup.set('Deg') rdoDeg = Radiobutton(root, text='Deg', width=2, variable=angGroup, value='Deg').grid(row=2, column=3) rdoRad = Radiobutton(root, text='Rad', width=2, variable=angGroup, value='Rad').grid(row=2, column=4) rdoGrad = Radiobutton(root, text='Grad', width=3, variable=angGroup, value='Grad').grid(row=2, column=5) # Buttons (8x6 array) btnRand = Button(root, text='Rand', width=6, command=actRand).grid(row=3, column=0) btnPi = Button(root, text='pi', width=6, command=actPi).grid(row=3, column=1) btnFact = Button(root, text='x!', width=6, command=actFact).grid(row=3, column=2) btnComb = Button(root, text='nCr', width=6, command=actComb).grid(row=3, column=3) btnPerm = Button(root, text='nPr', width=6, command=actPerm).grid(row=3, column=4) btnRec = Button(root, text='1/x', width=6, command=actRec).grid(row=3, column=5) btnSqr = Button(root, text='x^2', width=6, command=actSqr).grid(row=4, column=0) btnCube = Button(root, text='x^3', width=6, command=actCube).grid(row=4, column=1) btnPow = Button(root, text='x^y', width=6, command=actPow).grid(row=4, column=2) btnSin = Button(root, text='sin', width=6, command=actSin).grid(row=4, column=3) btnCos = Button(root, text='cos', width=6, command=actCos).grid(row=4, column=4) btnTan = Button(root, text='tan', width=6, command=actTan).grid(row=4, column=5) btnExp = Button(root, text='Exp', width=6, command=actExp).grid(row=5, column=0) btnDms = Button(root, text='dms', width=6, command=actDms).grid(row=5, column=1) btnLeftP = Button(root, text='(', width=6, command=actLeftP).grid(row=5, column=2) btnRightP = Button(root, text=')', width=6, command=actRightP).grid(row=5, column=3) btnLn = Button(root, text='ln', width=6, command=actLn).grid(row=5, column=4) btnLog = Button(root, text='log', width=6, command=actLog).grid(row=5, column=5) btnMod = Button(root, text='Mod', width=6, command=actMod).grid(row=6, column=0) btnMC = Button(root, text='MC', width=6, command=actMC).grid(row=6, column=1) btnMR = Button(root, text='MR', width=6, command=actMR).grid(row=6, column=2) btnMAdd = Button(root, text='M+', width=6, command=actMAdd).grid(row=6, column=3) btnMSub = Button(root, text='M-', width=6, command=actMSub).grid(row=6, column=4) btnPosNeg = Button(root, text='+/-', width=6, command=actPosNeg).grid(row=6, column=5) btnAnd = Button(root, text='And', width=6, command=actAnd).grid(row=7, column=0) btnNot = Button(root, text='Not', width=6, command=actNot).grid(row=7, column=1) btn7 = Button(root, text='7', width=6, command=act7).grid(row=7, column=2) btn8 = Button(root, text='8', width=6, command=act8).grid(row=7, column=3) btn9 = Button(root, text='9', width=6, command=act9).grid(row=7, column=4) btnDiv = Button(root, text='/', width=6, command=actDiv).grid(row=7, column=5) btnOr = Button(root, text='Or', width=6, command=actOr).grid(row=8, column=0) btnInt = Button(root, text='Int', width=6, command=actInt).grid(row=8, column=1) btn4 = Button(root, text='4', width=6, command=act4).grid(row=8, column=2) btn5 = Button(root, text='5', width=6, command=act5).grid(row=8, column=3) btn6 = Button(root, text='6', width=6, command=act6).grid(row=8, column=4) btnMult = Button(root, text='*', width=6, command=actMult).grid(row=8, column=5) btnXor = Button(root, text='Xor', width=6, command=actXor).grid(row=9, column=0) btnC = Button(root, text='C', width=6, command=actC).grid(row=9, column=1) btn1 = Button(root, text='1', width=6, command=act1).grid(row=9, column=2) btn2 = Button(root, text='2', width=6, command=act2).grid(row=9, column=3) btn3 = Button(root, text='3', width=6, command=act3).grid(row=9, column=4) btnSub = Button(root, text='-', width=6, command=actSub).grid(row=9, column=5) btnLsh = Button(root, text='Lsh', width=6, command=actLsh).grid(row=10, column=0) btnAC = Button(root, text='AC', width=6, command=actAC).grid(row=10, column=1) btn0 = Button(root, text='0', width=6, command=act0).grid(row=10, column=2) btnDec = Button(root, text='.', width=6, command=actDec).grid(row=10, column=3) btnEq = Button(root, text='=', width=6, command=actEq).grid(row=10, column=4) btnAdd = Button(root, text='+', width=6, command=actAdd).grid(row=10, column=5) # Display MEMORY whenever a number is stored in memory. lblMemory = Label(root, textvariable=memCapt).grid(row=0, column=3, columnspan=3) # Show the current number of open levels of parentheses. For example, if you press # AC and enter: 3*(4+(2^6)/(5+3, have this button show PAR = 2, because there are 2 open # levels of parentheses that are not closed. lblParen = Label(root, textvariable=parCapt).grid(row=0, column=0, columnspan=3) txtContents.set('0') txtNum = Entry(root, textvariable=txtContents, state='readonly', justify=RIGHT, width=45).grid(row=1, column=0, columnspan=6) # This is the display area, apart from the trail root.mainloop()