2
\$\begingroup\$

I've been trying to create a calculator to find mass using any and all known equations. The program will also return the steps used to find mass so the user can 'check their work' on physics assignments.

My biggest problem so far (and was solved by much copy-pasta) is the equations themselves. I'd like to be able to create an equation variable that contains other variables inside itself, if possible, I want the variable to state:

var.mass = var.force / var.acceleration && var.energy / var.c^2 && var.density / var.volume

How, if possible, would I go about creating this variable? I could certainly define a different variable for each equation, but that would be extremely time-consuming and I'm sure Python has something that could help! I haven't tried an array, and would prefer not to as I have very little experience with them. However, if someone could give me an idea, even just the command name I would be very appreciative!

Feel free to use the code however and with whatever you want.

#this script is for solving for mass
#Define variables
g = 9.8
c = 3.00 * 10 * 10 * 10 * 10 * 10 * 10 * 10 * 10
c2 = c * c
E = mass * c * c
#Ask if the user wants to see how problem was solved
show_work = input('Show work? ')
#Asks for variable input
force_val = float(input('Force? (In Newtons) '))
mass_val = float(input('Mass? (In kg) '))
acceleration_val = float(input('acceleration? (In m/s^2) '))
p_val = float(input('density? (In Kg/m^3) '))
volume_val = float(input('Volume? (m^3) '))
weight_val = float(input('Weight? (Normal Force) '))
energy_val = float(input('Energy? '))
kinetic_val = float(input('Kinetic Energy? '))
velocity_val = float(input('Velocity? (In m/s) '))
#Solve for mass based on known values
#show work off
if show_work == 'no':
 if mass_val > 0.00:
 print(mass_val)
 elif force_val > 0:
 if acceleration_val > 0:
 mass_val = force_val / acceleration_val
 print(mass_val)
 elif p_val > 0:
 if volume_val > 0:
 mass_val = p_val / volume_val
 print(mass_val)
 elif weight_val > 0:
 mass_val = weight_val / g
 print(mass_val)
 elif energy_val > 0:
 mass_val = energy_val / c2
 print(mass_val)
 elif kinetic_val > 0:
 if velocity_val > 0:
 mass_val = 1/2 * kinetic_val / velocity_val / velocity_val
 print(mass_val)
#show work on
if show_work == 'yes':
 if mass_val > 0.00:
 print(mass_val)
 elif force_val > 0:
 if acceleration_val > 0:
 mass_val = force_val / acceleration_val
 print('Force = Mass * Acceleration ')
 print('Mass = Force / Acceleration ')
 print('Mass =', force_val, '/', acceleration_val)
 print('Mass =', mass_val)
 elif p_val > 0:
 if volume_val > 0:
 mass_val = p_val / volume_val
 print('Mass = Density / Volume ')
 print('Mass =', p_val, '/', volume_val)
 print('Mass =', mass_val)
 elif weight_val > 0:
 mass_val = weight_val / g
 print('Mass = Weight / Gravity ')
 print('Mass =', weight_val, '/', g)
 print('Mass =', mass_val)
 elif energy_val > 0:
 mass_val = energy_val / c2
 print('E=mc^2')
 print('m=E/c^2')
 print('Mass =', energy_val, '/', 'c^2')
 print('Mass =', mass_val)
 elif kinetic_val > 0:
 if velocity_val > 0:
 mass_val = 2 * kinetic_val / velocity_val / velocity_val
 print('KE = 1/2mv^2')
 print('Mass = 2(KE/v^2)')
 print('Mass =', kinetic_val, '/', velocity_val, '^2')
 print('Mass =', mass_val)
 print(mass_val)
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Mar 30, 2014 at 7:15
\$\endgroup\$
4
  • 2
    \$\begingroup\$ I don't think you can blindly apply Physics formulas like that. The appropriate formula to choose depends entirely on context. For example, there are many processes to obtain different kinds of energy from a material; pure energy-mass conversion is pretty rare. \$\endgroup\$ Commented Mar 30, 2014 at 8:01
  • \$\begingroup\$ Are we talking specifically the E=mc^2 formula, or did you mean as a generalization of the calculator as a whole? \$\endgroup\$ Commented Mar 30, 2014 at 8:38
  • \$\begingroup\$ I think that the calculator concept is fundamentally flawed; E = mc^2 is just an example. \$\endgroup\$ Commented Mar 30, 2014 at 8:45
  • \$\begingroup\$ Ah, well thanks for the input ^_^ I'm just trying to come up with a calculator that will work in my conceptual physics course, I have thought of many issues myself in the application of it, but if I'm going to fail, I'll at least fail in the most time-consuming way I can. \$\endgroup\$ Commented Mar 30, 2014 at 8:51

1 Answer 1

7
\$\begingroup\$

I’m not going to have a go at the big problem of "equation variable" (which might be better suited to Stack Overflow), but I do have some comments on your existing code:

  • Python uses the operator ** for powers; i.e., a ** b means "a to the power b". You can use this to tidy up your constants at the top of the file:

    c = 3.00 * 10 ** 8
    E = mass * c ** 2
    

    I think that’s easier to read, and makes it clear where they’re coming from.

    I see no reason to define a c2 variable, especially when you use it inconsistently (sometimes you have c2, sometimes c * c.

    The scipy.constants module contains lots of these constants built-in to high levels of precision, but that may be inappropriate for your work.

  • At the point when E is defined, the variable mass hasn’t been defined. In fact, I can’t find any mention of the variable in the script. What’s it doing here?

  • Something only happens if the user types exactly yes or no when asked "Show work?" You might be better off defining a list of "acceptable" responses which means the user wants their work shown.

    For example:

    yes_list = ['yes', 'y', 'true', 't', 'yep']
    if input('Show work?').lower() in yes_list:
     show_input = True
    else:
     show_input = False
    
  • Most of the code is duplicated: once in the branch of the if statement which shows the working, and again in the branch which doesn’t. You’d be better off defining a working_print function which only prints anything if the user wants it. Further, you can skip defining a show_input variable, and get it directly from the user input:

    yes_list = ['yes', 'y', 'true', 't', 'yep']
    if input('Show work?').lower() in yes_list:
     def working_print(x):
     print(x)
     return None
    else:
     def working_print(x)
     return None
    

    Then you can replace instances of print() which are optional with working_print(). For example, the branch

    print('E=mc^2')
    print('m=E/c^2')
    print('Mass =', energy_val, '/', 'c^2')
    print('Mass =', mass_val)
    

    would become

    working_print('E=mc^2')
    working_print('m=E/c^2')
    working_print('Mass =', energy_val, '/', 'c^2')
    print('Mass =', mass_val)
    
  • You have lots of nested if statements of the form

    elif p_val > 0:
     if volume_val > 0:
     # code goes here
    elif something_else
    

    I think you’d be better off combining the elif and the if into a single line, e.g. something like

    if p_val > 0 and volume_val > 0
    if min(p_val, volume_val) > 0
    

    It makes it easier to see what the conditions for each branch are. It also leaves you open to less unexpected bugs if none of the branches get run correctly.

    And why p_val instead of density_val?

  • Add an else block at the end of the code which lets you know when it got there, even if it prints something as silly as "Uh oh, don’t know how I got here." It makes life easier when debugging – you can tell whether none of your branches ran, or whether one of the branches ran but aren’t printing anything.

  • In several places, you’re checking that variables are positive where it doesn’t seem appropriate.

    For example, consider the F = ma branch. Both force and acceleration are vectors, so it makes sense for them both to be negative (corresponding to force/acceleration in the opposite direction). When computing mass, all you require is that they both have the same sign. So your if statement should become

    if force_val * acceleration_val > 0
    

    Velocity is also a vector, so it can be signed, and I see no reason why energy (or several other quantities) have to be non-zero.

  • There’s a great app called Pythonista for iOS which can edit and run Python scripts. (It doesn’t do Python 3, but your script is sufficiently simple that converting to run on 2.x shouldn’t cause any problems.) I don’t know enough about other platforms to suggest anything else.

answered Mar 30, 2014 at 8:42
\$\endgroup\$
3
  • 3
    \$\begingroup\$ You could just write c = 3e8. \$\endgroup\$ Commented Mar 30, 2014 at 8:47
  • \$\begingroup\$ I cannot upvote you due to being a new member and requiring 15 rep, but when I get it, I will upvote. \$\endgroup\$ Commented Mar 30, 2014 at 8:53
  • \$\begingroup\$ The random, unspecified junk variable for E and mass were from previous attempts that I did not clean... now that you point it out, I'm surprised the program ran at all. Normally it (IDLE 3) gives an error when a variable is not defined... Thank you so much for the help! \$\endgroup\$ Commented Mar 30, 2014 at 8:55

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.