diff -r 7316dc5f61ef -r ad27ab7e6fb6 calc.py --- a/calc.py Mon May 04 02:19:21 2015 +0300 +++ b/calc.py Mon May 04 02:46:09 2015 +0300 @@ -120,7 +120,7 @@ 'pow': { 'symbol': '**', 'operands': 2, 'priority': 10, 'function': lambda x, y: x ** y }, 'mul': { 'symbol': '*', 'operands': 2, 'priority': 50, 'function': lambda x, y: x * y }, 'div': { 'symbol': '/', 'operands': 2, 'priority': 50, 'function': lambda x, y: x / y }, - 'mod': { 'symbol': '%', 'operands': 2, 'priority': 50, 'function': lambda x, y: math.fmod (x, y) }, + 'mod': { 'symbol': '%', 'operands': 2, 'priority': 50, 'function': realf (math.fmod) }, 'add': { 'symbol': '+', 'operands': 2, 'priority': 100, 'function': lambda x, y: x + y }, 'sub': { 'symbol': '-', 'operands': 2, 'priority': 100, 'function': lambda x, y: x - y }, 'eq': { 'symbol': '==', 'operands': 2, 'priority': 500, 'function': lambda x, y: x == y }, @@ -150,6 +150,14 @@ def sgn (x): return cmp (x, 0) +def integerclamp (x, bits, signed): + x = x % (2 ** bits) + + if signed and x >= (2 ** (bits - 1)): + x = -(2 ** bits) + x + + return x + Constants = { 'pi': cmath.pi, 'e': cmath.e, @@ -195,6 +203,14 @@ 'conjugate':{ 'function': lambda x: x.conjugate() }, 'rand': { 'function': random.random }, 'sgn': { 'function': realf (sgn) }, + 'byte': { 'function': intf (lambda x: integerclamp (x, bits=8, signed=False)) }, + 'sbyte': { 'function': intf (lambda x: integerclamp (x, bits=8, signed=True)) }, + 'word': { 'function': intf (lambda x: integerclamp (x, bits=16, signed=False)) }, + 'sword': { 'function': intf (lambda x: integerclamp (x, bits=16, signed=True)) }, + 'dword': { 'function': intf (lambda x: integerclamp (x, bits=32, signed=False)) }, + 'sdword': { 'function': intf (lambda x: integerclamp (x, bits=32, signed=True)) }, + 'qword': { 'function': intf (lambda x: integerclamp (x, bits=64, signed=False)) }, + 'sqword': { 'function': intf (lambda x: integerclamp (x, bits=64, signed=True)) }, } Tokens = ['(', ')'] @@ -244,6 +260,9 @@ Attributes['dec'] = Attributes['decimal'] AttributeNames = sorted ([key for key in Attributes], key=lambda x:len(x), reverse=True) +def is_int (x): + return math.fabs (x - math.floor(x)) < epsilon + class Calculator (object): def __init__ (self): self.preferred_base = None @@ -520,7 +539,7 @@ printFunc (self.tabs + 'Evaluating function call: %s' % (sym)) expr[i] = Functions[sym.funcname]['function'] (*sym.args) printFunc (self.tabs + '-> %s' % expr[i]) - + i += 1 printFunc (self.tabs + 'Evaluate: %s' % expr) @@ -559,7 +578,7 @@ def repr_number (self, x): """Returns a string representation for a real number""" base = self.preferred_base if self.preferred_base else 10 - if math.fabs (x - math.floor(x)) < epsilon and base != 10: + if is_int (x) and base != 10: digits='0123456789abcdef' assert base <= len (digits), '''base %d is too large''' % base @@ -568,6 +587,12 @@ x = int (x) runaway = 0 + if not x: + return '0x0' + + if x < 0: + return '-' + self.repr_number (abs (x)) + while x > 0: runaway += 1 if runaway > 1000: