Skip to content

Instantly share code, notes, and snippets.

@PeterMinin
Last active July 6, 2023 19:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PeterMinin/c8711f482dafbb1ff40b to your computer and use it in GitHub Desktop.
Save PeterMinin/c8711f482dafbb1ff40b to your computer and use it in GitHub Desktop.
A command-line calculator with some handy and/or neat features.
#!/usr/bin/python
"""
A command line calculator with the following features:
1) Accepts numbers with any decimal and thousand separators.
2) Uses Decimal when possible, which favors "user-friendliness" of results
over speed of computation.
"""
from __future__ import division, print_function
try:
input = raw_input
except NameError:
pass
from math import *
import decimal
from decimal import Decimal
from functools import partial
import sys
import re
import traceback
import readline
num_regex = re.compile(r'\b[0-9.,]+(?: [0-9.,]+)*\b')
replacements = [
# (re.compile(r'(?<=[\d\s\)])x(?=[\s\d\(])'), '*'), # Multiplication as 'a x b'
# (re.compile(r'\^'), '**'), # Power as 'a^b'
]
def normalize_number(number: str):
separators = re.sub(r'\d', '', number, flags=re.U)
for sep in separators[:-1]:
number = number.replace(sep, '')
if separators:
sep = separators[-1]
number = number.replace(sep, '.' if sep!=' ' else '')
return number
def preprocess_number(match: re.Match, use_decimal):
number: str = match.group()
number = normalize_number(number)
if use_decimal:
decimal_number_str = f'Decimal("{number}")'
return decimal_number_str
else:
return number
def compute_expression(expr, use_decimal):
expr = re.sub(num_regex, partial(preprocess_number, use_decimal=use_decimal), expr)
for regex, repl in replacements:
expr = re.sub(regex, repl, expr)
print(eval(expr))
def enter_calc_prompt():
decimal_context = decimal.getcontext()
decimal_context.rounding = decimal.ROUND_HALF_UP
while True:
try:
expr = input("> ")
if expr in ["q", "quit", "exit"]:
break
if not expr:
continue
try:
compute_expression(expr, use_decimal=True)
except TypeError:
compute_expression(expr, use_decimal=False)
except (EOFError, SystemExit):
print()
break
except:
traceback.print_exc()
if __name__ == "__main__":
if len(sys.argv) == 1:
enter_calc_prompt()
else:
compute_expression(' '.join(sys.argv[1:]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment