Last active
July 6, 2023 19:30
A command-line calculator with some handy and/or neat features.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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