How do I let the program understand the input - python

I'm making a calculator that can add, subtract, multiply, and divide algebraic terms. I've already made a class that can "make" the algebraic terms, and as of now I want the computer to ask me for an algebraic expression, read it, then register it as one. (I'm really not sure about the correct wording, forgive me, I am new to coding.)
# Make a calculator that adds, subtracts, multiplies, and divides algebraic expressions.
# An algebraic expression has: a coefficient, a variable, and a power
# Class that makes the algebraic expression
class ExpressionMaker:
# Defines the coefficient, variable, and power of the algebraic term.
def __init__(self, coefficient, variable, power):
self.coefficient = coefficient
self.variable = variable
self.power = power
# Types down/returns/defines? the whole algebraic expression as one term.
def term(self):
return "{}{}^{}".format(self.coefficient, self.variable, self.power)
# Examples of algebraic terms of varying coefficients, variables, and powers.
expression_1 = ExpressionMaker(7, "x", 1)
expression_2 = ExpressionMaker(4, "y", 1)
expression_3 = ExpressionMaker(-3, "a", 2)
# Make the program understand what the user inputs and convert it into an algebraic expression.
# Make the program add the algebraic expressions from the user.
# An algebraic term has: a coefficient, a variable, and a power.
# Let the program check if the input has those 3 and if they are in the right order.
expression_holder1 = input("What is your first algebraic expression?: ")
print("You first algebraic expression is: " + expression_holder1)
I'm really not sure what to do after this. The most I've been able to think about was to use "If statements" to check if the expression_holders have an integer(for the coefficient), string(for the variable), and I don't know what to check for the power. I also don't know how to check if the order is correct. For example, the correct input would be 7x^3 but what if they instead type x7^3. And if the input is wrong, how do I let the user know that and let them type again?

This solution uses regular expression to split the coefficient and variable apart. The power is retrieved using parition. It prints an error if the format of the given input is incorrect.
import re #adds regular expression module
#Code for class can go here
while True:
try:
expression_holder1 = input("What is your first algebraic expression?: ")
expression = expression_holder1.partition("^") #Paritions the expression using the ^, the power if stored in the 2nd index
coefficient_variable = expression[0] #THe coefficient and varible is stored in the first index
res = re.split('(\d+)', coefficient_variable) #Uses regular expression to split the character and number
power = expression[2] # Stores the value of given power
coefficient = res[1] # store the value of coefficient
variable = res[2] # Stores the varible given
if power.isdigit() == False or coefficient.isdigit() == False or variable.isalpha() == False:
print("Wrong input") #prints error if the incorrect format is given
else:
break
except IndexError: #prints error if a coefficient, variable or power is missing
print("Index Error -> Wrong input")
expression1 = ExpressionMaker(coefficient, variable, power)
print(expression1.term())

Related

I am writing a program that accepts user input in order to differentiate a function

In order to find the maximums and minimums of a function, I am writing a program that accepts a polynomial imputed from the user and finds where the derivative = 0.
from sympy import Symbol, Derivative
from sympy import symbols, Eq, solve
import sympy as sy
import numpy as np
import math
x= Symbol('x', real = True)
function= x**4 +7*x**2 +8
deriv= Derivative(function, x)
yprime = deriv.doit()
y = symbols('x')
eq1 = Eq(yprime,0)
sol = solve(eq1, )
The only reason that the code above is able to take the derivative and find solutions is because the coefficients and exponents are integers. If I ask for user input {e.g., function = input("What is your function: ")}, then the whole thing will become a string and SymPy can not take the derivative.
Is it possible to turn the coefficients and exponents into integers and leave the rest of the function as a string so that I can take the derivative?
If your equation can be arbitrarily complicated, you might want to use eval to parse it from Python syntax. Now, eval is generally unsafe to use on untrusted user input, but a user replying to an input() prompt is probably trusted (since they're usually sitting at the computer running the code).
So one option is:
function = eval(input("What is your function: "))
If placed just below the definition of x, it will allow that variable to be used in the equation. You could also provide a namespace for eval to use, rather than letting it use your function's local namespace (e.g. function = eval(input(...), {'x': Symbol('x', real=True)})).
If your problem space is more limited, and you only need to handle equations that are polynomials with integer coefficients, then you could write your own logic to input the equation in a much more simplified form. For instance, you could loop, asking for the coefficients in order (probably from the lowest exponent to the highest). Try something like this:
import itertools
from sympy import Symbol
x = Symbol('x', real = True)
function = 0
for exponent in itertools.count():
coef = input(f"Enter coefficient for x**{exponent} (or give an empty value to be done): ")
if not coef:
break
function += int(coef) * x**exponent
print("Polynomial so far:", function)
For the example equation in your question, you'd enter 8, 0, 7, 0, 1 and finally an empty input.
The better thing to do is to turn your string into a SymPy expression. As long as the user uses SymPy/python syntax, sympyify will convert it for you:
>>> from sympy import sympify, solve
>>> user='3*x**2-1'
>>> eq = sympify(user)
>>> x = eq.free_symbols.pop() # assuming there is 1 symbol
>>> solve(eq.diff(x))
[0]

Is isinstance() function not enough to detect integers and floats?

I'm making a very basic calculator as my first project (I'm learning Python and want something to show what i've learned so far) and as it is right now, the program works fine.
As it is right now, I have a function to validate user inputs so that the code only accepts numbers and decimal points, and returns the input as a float value to be calculated.
However, I would like to make it so that the code can recognize if the user is entering an Integer or a Float value, so that a simple operation such as "2+2" doesn't return a float "4.0" result, and just a "4".
The function that I have working right now is the following:
def valid_num():
number = ''
valid = True
while valid:
try:
number = float(input('───→ '))
break
except ValueError:
print('')
print('Invalid input (numbers and decimal points only).')
return number
To be able to diferentiate between integers and float values, I looked up methods and found the isinstance() function, which I may not be applying correctly... This is the function that I'm trying to make work:
def valid_num():
number = ''
valid = True
while valid:
number = input('───→ ')
check_int = isinstance(number, int)
if check_int:
number = int(number)
break
check_float = isinstance(number, float)
if check_float:
number = float(number)
break
if not check_int and not check_float:
print('Invalid input (numbers and decimal points only).')
return number
Sorry if there's an obvious error I'm not seeing, I'm just starting to code... Thanks in advance for any help you can provide =D
As pointed out by #tim-roberts, isinstance(number, int) checks the type of number, which is a string.
To distinguish ints and floats, you have a couple of options:
Try to convert it to int, if that fails try to convert to float; this would use a pair of try/except clauses.
Validate the input as text, checking that it follows the rules you set for your calculator, probably using regular expressions; this would let you positively assert that it matches what you expect, rather than whatever the int and float functions accept.
You could also work throughout in float (or Decimal), then convert 4.0 to 4 on output; that would mean that you'd also get "4" for "0.5 * 8" (which may be better or worse than getting "4.0"; that's up to your UX design).

Number eval issue python

I want to evaluate the following differential using the values in list y however I cant figure out what I am doing wrong. I am supposed to get 1.9256 for y=5, 1.9956 for y=10 and 2.1356 for y=20. What I'm trying to do is ask the user to input an equation with x as its variable, derive this equation with respect to x, ask the user to input as many values as he wants and evaluate the expression using these inputted values. Thanks for your help.
import sympy as sym
print('Sensitivity: ')
#exp = input('Enter the expression to find the sensitivity: ')
exp='(0.007*(x**2))+(1.8556*x)-1.8307'
#values=list(map(float,input('Enter the values at which you want to compute the sensitivity seperated by spaces: ').split()))
values=[5,10,20]
x=sym.Symbol('x')
differential=str(sym.diff(exp,x))
print(differential)
for i in y:
expression=differential.replace(str(x),str(values))
value=eval(expression)
print('The sensitivity at',i,'is: ',value)
What I believe you intended to write is:
import sympy as sym
exp='(0.007*(x**2))+(1.8556*x)-1.8307'
values=[5,10,20]
x=sym.Symbol('x')
differential=str(sym.diff(exp,x))
print(differential)
for value in values:
expression=differential.replace(str(x),str(value))
result=eval(expression)
print('The sensitivity at',value,'is: ',result)
...which emits as output:
The sensitivity at 5 is: 1.9256
The sensitivity at 10 is: 1.9956
The sensitivity at 20 is: 2.1356
Note the changes:
We're iterating for value in values -- values exists, y does not.
We're assigning the eval result to a separate variable (in this case, result)
This still is not by any means good code. Good code would not do string substitution to substitute values into code. Substituting repr(value) instead of str(value) would be at least somewhat less broken.

Fraction calculator in python workaround

So, I have to create a python script that given 2 fractions and an operand will print the result of the operation. This was intended to be solved by firstly asking for one fraction and saving it into a variable, then ask for another fraction and lastly ask for the operand. But out of curiosity I've tried to give this problem a different point of view.
My idea was to ask for the full operation and save the input string into a variable, then with the function exec() I could get the decimal result of the given operation, finally to deal with decimals my idea was to multiply by 10 to the power of the number of decimal digits and then dividing by 10 to that same power, this way I could have a fraction as a result. So I went on to code and managed to program this out, my only issue is that the number of decimal digits is limited so normally the result that my script returns is a very big fraction that is very close to what the real fraction is. So I was wondering if there is any workaround for this. Here is my code and an example for further explanation:
op = input('Enter operation: ')
try:
exec('a = ' + op)
except:
print('Invalid operation')
def euclides(a, b):
while a != 0 and b != 0:
if a < b: b = b%a
else: a = a%b
if a == 0: return b
elif b == 0: return a
print(f'{int(a*10**len(str(a).split(".")[1])/euclides(a*10**len(str(a).split(".")[1]),10**len(str(a).split(".")[1])))}/{int(10**len(str(a).split(".")[1])/euclides(a*10**len(str(a).split(".")[1]),10**len(str(a).split(".")[1])))}')
EXAMPLE:
op input => 4/3+5/7
Result of script => 5119047619047619/2500000000000000 = 2.04761904761
Result I'm looking for => 43/21 = 2.047619 period
Thank you for your help in advance
What are your constraints as to what standard or add-on modules you can use? Without taking into account constraints you haven't specified, there are much better ways to go about what you're doing. Your problem seems to be summed up by "the result that my script returns is a very big fraction" and your question seems to be "I was wondering if there is any workaround for this?". There are a number of "work arounds". But it's pretty hard to guess what the best solution is for you as you don't tell us what tools you can and can't use to accomplish your task.
As an example, here's an elegant solution if you can use regular expressions and the fractions module, and if you can assume that the input will always be in the very strict format of <int>/<int>+<int>/<int>:
import re
import fractions
op = input('Enter operation: ')
m = re.match(r"(\d+)/(\d+)\+(\d+)/(\d+)", op)
if not m:
raise('Invalid operation')
gps = list(map(int, m.groups()))
f = fractions.Fraction(gps[0], gps[1]) + fractions.Fraction(gps[2], gps[3])
print(f)
print (float(f))
print(round(float(f), 6))
Result:
43/21
2.0476190476190474
2.047619
This answers your current question. I don't, however, know if this violates the terms of your assignment.
Could just turn all natural numbers into Fractions and evaluate:
>>> op = '4/3+5/7'
>>> import re, fractions
>>> print(eval(re.sub(r'(\d+)', r'fractions.Fraction(\1)', op)))
43/21
Works for other cases as well (unlike the accepted answer's solution, which only does the sum of exactly two fractions that must be positive and must not have spaces), for example:
>>> op = '-1/2 + 3/4 - 5/6'
>>> print(eval(re.sub(r'(\d+)', r'fractions.Fraction(\1)', op)))
-7/12
Checking:
>>> -7/12, -1/2 + 3/4 - 5/6
(-0.5833333333333334, -0.5833333333333334)

Python creating a calculator

I am fairly new to python.
I have been asked to create a calculator using only string commands, conversions between int/string/float etc.(if needed), and using functions is a requirement. while and for loops can also be used.
The program needs to take an input of the form x/y or x/y/z, where x y z are any positive or negative number. Where "/" can be replaced by addition multiplication and subtraction as well. And where any number of white spaces can exist between operands and operators. This is an idea of what I have so far.
I would have a unique definition for +,-,/, and *. I would create a function for what the user inputs. I would use ".lstrip" and ".rstrip" to get rid of white spaces.
Now what I am having trouble with is creating the input function. I am very new to functions and this is basically what I have. I know it isn't much to work with but I am really stuck on how to properly enter the function.
def multiplication(x,a,y,b,z):
if (a== "*"):
return x*y
if (b== "*"):
return y*z
def division(x,a,y,b,z):
if (a== "/"):
return x/y
if (b== "/"):
return y/z
def addition(x,a,y,b,z):
if (a== "+"):
return x+y
if (b== "+"):
return y+z
def subtraction(x,a,y,b,z):
if (a== "-"):
return x-y
if (b== "-"):
return y-z
def (x,y,z):
x=0
y=0
z=0
zxc=int(input()):# this is where I get stuck and I don't know how to implement x,y,z into the input.
All help is appreciated. If you are unsure of whether the code you provide is too intense for my needs, please ask before wasting your time for me, making code that I can't possibly use. I promise to reply ASAP.
Basically I am trying to find a way to split the inputted string AND THEN start calculations with it.
Since this looks like homework, I doubt the OP is allowed to use the typical ways to solve the problem. I think this is an exercise in input validation and string manipulation; followed by program flow and understanding function return values.
There are two things you need to do here:
Figure out what would be valid inputs to your program.
Keep prompting the user till he or she enters input that is valid for your program.
For #1, we know that valid inputs are numbers (positive or negative integers), and they must be in the form of an expression. So this means, the minimum length of the input will be three (two numbers and a math symbol) and characters (strings) in the input are not valid.
This is our basic loop to get the user's input:
expression = raw_input('Please enter the expression: ')
expression_result = check_input(expression)
while not expression_result:
print 'You did not enter a valid expression'
expression = raw_input('Please enter the expression: ')
expression_result = check_input(expression)
The check_input method will validate whatever the user entered is accurate based on our rules:
def check_input(input_string):
# Check the basics
if len(input_string) < 3:
return False
# Check if we are getting passed correct characters
for character in input_string:
if character not in '1234567890' or character not in '/*+-':
return False
# Things like /23 are not valid
if input_string[0] in '/*+':
return False
return input_string
After you have the correct input, the next step is to split the input into the various parts that you need to feed to your math functions. I'll leave that part up to you.
Assuming you have the correct string (that is, it is valid input for your program), you now need to split it into two parts.
The operator (the math symbol)
The operands (the numbers surrounding the math symbol)
So we know that we have a limited set of operators +,-,/,*, so one idea is to use the split() method of strings. This works well:
>>> s = '4+5'
>>> s.split('+')
['4', '5']
You would try splitting the string with all of your operators and then check the results. Note that splitting a string with a character that doesn't exist won't raise any errors, but you'll just the string back:
>>> s = '4+5'
>>> s.split('/')
['4+5']
So one approach is - split the string on the operators, if the resulting list has length > 2, you know that the first member of the resulting list is the left hand side of the operator, and the second member of the list is whatever is on the right hand side.
This works fine with positive numbers, with negative numbers however:
>>> s = '-4+3'
>>> s.split('-')
['', '4+3']
Good news is we aren't the first ones to reach this problem. There is another way to evaluate equations, called the Polish notation (also called prefix notation). Here's the algorithm from the wikipedia page:
Scan the given prefix expression from right to left
for each symbol
{
if operand then
push onto stack
if operator then
{
operand1=pop stack
operand2=pop stack
compute operand1 operator operand2
push result onto stack
}
}
return top of stack as result
To get a normal expression (called infix) to the polish flavor, use the shunting yard algorithm, which is my favorite train-based algorithm in computer science.
Use shunting yard to convert your expression to Polish notation, then use the pseudo code to solve the equation. You can use lists as your "stack".
Keep in mind all your inputs are in strings, so make sure you convert them to integers when you are doing the actual math.
If you're making just a toy calculator, eval() accepts local and global variables, so you could use something like this:
def calculate(x=0, y=0, z=0):
expression = raw_input('Enter an expression: ')
return eval(expression, None, locals())
Here's a sample console session:
>>> calculate()
Enter an expression: x + 5 - y
5
Note that eval() is not secure. If you want to make something serious, you will have to parse the expression.
Also, since your expressions are simple, you could use a regex to validate the input before evaling it:
def validate(expression):
operator = r'\s*[+\-/*]\s*'
return bool(re.match(r'^\s*(?:x{o}y|x{o}y{o}z)$'.format(o=operator), expression))
Here is a possible solution outline using regular expressions. Error checking left as exercise. If this isn't homework and you'd like to see the fleshed-out solution, view it here
import re
# input is a list of tokens (token is a number or operator)
tokens = raw_input()
# remove whitespace
tokens = re.sub('\s+', '', tokens)
# split by addition/subtraction operators
tokens = re.split('(-|\+)', tokens)
# takes in a string of numbers, *s, and /s. returns the result
def solve_term(tokens):
tokens = re.split('(/|\*)', tokens)
ret = float(tokens[0])
for op, num in <FILL THIS IN>:
# <apply the operation 'op' to the number 'num'>
return ret
# initialize final result to the first term's value
result = solve_term(tokens[0])
# calculate the final result by adding/subtracting terms
for op, num in <FILL THIS IN>:
result += solve_term(num) * (1 if op == '+' else -1)
print result
I have an alternative to your code. The user can enter stuff like: 8*6/4-3+3 and this will still work. It also will not crash if a letter (d, a, s) is entered. Very compact.
Code (Python v3.3.0):
valid_chars = "0123456789-+/* \n";
while True:
x = "x="
y = input(" >> ")
x += y
if False in [c in valid_chars for c in y]:
print("WARNING: Invalid Equation");
continue;
if(y == "end"):
break
exec(x)
print(x)

Categories