Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
decimal + fraction
#1
hello! I wish to be an amazing coder one day, but right now, I am struggling with a simple calc. I want the calc to be supportive of decimal + fractions, an example would be: 1/1.9 * 9/7.6 = {results} | my code is:

f
rom fractions import Fraction
while True:
    print("1. Division")
    print("2. Multiplication")
    print("3. Addition")
    print("4. Subtraction")
    x = input("What do you choose?: ")
    num1 = Fraction(input("Your first Number: "))
    num2 = Fraction(input("Your second number: "))
    if x == "1":
        print("Outcome:", num1 / num2)
    elif x == "2":
        print("Outcome:", num1 * num2)
    elif x == "3":
        print("Outcome:", num1 + num2)
    elif x == "3":
        print("Outcome:", num1 - num2)
    else:
        print("Invalid Syntax!")
Reply
#2
One way to do this is to use eval(). eval() evaluates a string of Python code.

So without any input checks you can do this:

# user will need to get the input right 
string = input('Enter a number, an operator then another number.')
print(eval(string))
However, eval() will try to run any code you feed it as a string, so that could be a security problem in a real-life setting.

This works for me:

import operator

# a dictionary of operators linked to the module operator
# the module operator has many more mathematical functions
# add what you like
my_operators = {
    '+': operator.add, 
    '*': operator.mul,
    '-': operator.sub,
    '/': operator.truediv,
    'q': 'Quitting'}   


def check_operator():
    op = 'y'
    while not op in my_operators.keys():
        op = input("Enter /, *, +, -, or q to quit. ")
    return op
    

def calc(op,num1, num2):
    return my_operators[op](num1,num2)
            

# keep looping until q is entered
while True:
    op = check_operator()
    if op == 'q':
        break
    else:
        num1 = float(input('Enter a number ... '))
        num2 = float(input('Enter a number ... '))
        result = calc(op, num1,num2)
        print(f'The amazing result of {num1} {op} {num2} is: {result}')
You still need a way to check the num1 and num2 are in fact numbers.

Maybe use:

isinstance(num, float)
Output:
isinstance(1.2, float) True
Or a regex expression to confirm that num1 and num2 are floating point numbers.
Reply
#3
1/1.9 is not a fraction because 1.9 is not a rational number. 1/1.9 is an equation. You could write a function that takes a simple equation and returns the result as a fraction.
from fractions import Fraction


def bad_fraction(value):
    try:
        return Fraction(value)
    except ValueError:
        if isinstance(value, str) and "/" in value:
            num, denom = value.split("/")
            return Fraction(float(num) / float(denom))
        raise


while (inp := input("Enter bad fraction: ")):
    print(bad_fraction(inp))
I think it would make more sense to write your program to take input in the form of an equation and solve. The Python ast module makes this easy.
import ast
import operator


def solve(equation):
    """Return solution to equation."""

    def op(ast_op):
        """Return operator function associated with ast_op."""
        ops = {
            ast.Add: operator.add,
            ast.Sub: operator.sub,
            ast.Mult: operator.mul,
            ast.Div: operator.truediv,
            ast.USub: operator.neg,
        }
        try:
            return ops[type(ast_op)]
        except KeyError:
            raise ValueError(f'Unsupported operator "{ast_op.__class__.__name__}".')

    def evaluate(tree):
        """Recursively traverse the abstract syntax tree, solving the left and right
        branches until all branches are solved.  Return result.
        """
        if isinstance(tree, ast.BinOp):
            return op(tree.op)(evaluate(tree.left), evaluate(tree.right))
        elif isinstance(tree, ast.UnaryOp):
            return op(tree.op)(evaluate(tree.operand))
        elif isinstance(tree, ast.Constant):
            return tree.value
        else:
            raise TypeError("Invalid equation.")

    return evaluate(ast.parse(equation, mode="eval").body)


print(solve("1 / 1.9 * 9 / 7.6"))
print(solve("1 + 2 * 3"))
print(solve("(1 + 2) * 3"))
print(solve("2**4"))
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  method to remove zero digits from fraction in decimal Skaperen 17 6,322 Oct-23-2022, 04:02 AM
Last Post: Skaperen
  Fraction Calculation with Limitations TINMAN01 13 8,125 Dec-22-2020, 04:45 AM
Last Post: bowlofred
  fraction module: can you stop the reducing? qmfoam 1 3,404 Oct-10-2020, 06:10 PM
Last Post: bowlofred
  testing for Decimal w/o importing decimal every time Skaperen 7 6,057 May-06-2019, 10:23 PM
Last Post: Skaperen
  whole number and fraction Skaperen 11 7,812 Mar-17-2019, 11:33 PM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020