I'm trying to improve my code so this is about a 'problem notification' telling me that a variable can be undefined.
This is my code:
print('\nWindow types')
print('1:1200 x 1300 mm')
print('2:800 x 1000 mm')
print('3:2100 x 1500 mm')
Window_Dimension = float(input('Select window type: '))
if Window_Dimension == 1:
A = 1200
B = 1300
elif Window_Dimension == 2:
A = 800
B = 1000
elif Window_Dimension == 3:
A = 2100
B = 1500
else:
print('Invalid input!')
Lip_height = float(input('\nEnter lip eight (mm): '))
SWind_velocity = 80 # m/s Static wind velocity
print('Assuming a peak wind velocity of: 80 m/s')
Wind_pressure = (SWind_velocity ** 2) / 1600 # kN/m^2
print('Wind pressure (kN/m^2):', Wind_pressure)
a = A - (2 * Lip_height)
b = B - (2 * Lip_height)
Lip_area = (A * B) - (a * b) # m^2
Lip_pressure = (Wind_pressure * (A * B) / 1000000) / (Lip_area / 1000000) # kN/m^2
print('Uniform pressure on the lip (kN/m^2): ', round(Lip_pressure, 3))
and it works just fine, but I keep getting a problem notification about this two lines:
a = A - (2 * Lip_height)
b = B - (2 * Lip_height)
telling me that A and B can be undefined. I don't know if there's is a way to fix this, or even if I should fix it, but I'm new in python and I'm trying to avoid future "coding bad habits". Thanks
Don't simply print an error message and proceed when something goes wrong. Throw an exception. Instead of
print('Invalid input!')
Consider
raise Exception('Invalid input!')
As far as I can tell, it works perfectly. I don't get any error. Perhaps you need to define the variables right at the beginning.
Right at the beginning, add this in:
a = 0
b = 0
This set the variables right at the beginning, without a calculation. Later on, it would only rewrite the variable, not create it.
Let me know if this worked!
Related
First of all; english is not my main language so bare in mind. (The text in the script is in norwegian, I will try to translate as well as possible)
I am trying to create a python script that solves a second degree equation or a quadratic? equation I think. If i understand it correctly I should use cmath module to be able to solve complex roots, however, I havent got that far in my class yet and it is my task to only use math module and return a answer that looks something like this (if the roots are complex): "There is no real solution".
Also, when using normal math module I get returned a "math domain error" when trying to for example put a = 6, b = 11 and c = 32.
Thank you in advance.
Edward
Trying to use a if/elif/else thingy, have tried cmath (it returns a waaaay to long and unreadable answer)
My code is here under this (hopefully I have pasted it correctly, sorry in advance:
#Importerer math
import math
print("Programmet skal løse andregradslikningen ")
print("ax^2 + bx + c = 0 ved hjelp av abc-formelen")
print("Skriv inn verdiene for a, b og c.")
a = float(input('a = '))
b = float(input('b = '))
c = float(input('c = '))
d = (b**2) - (4*a*c)
sol1 = (-b+math.sqrt(d))/(2*a)
sol2 = (-b-math.sqrt(d))/(2*a)
if d < 0:
print("Likningen har ingen løsning")
elif d==0:
print(f"Løsning x = {-b/(2*a)}")
else:
print("Løsningen er")
print(f"x = {sol1}, og x= {sol2}")
You have to check if d is negative before you try to call math.sqrt(d), so you don't get an error.
d = (b**2) - (4*a*c)
if d < 0:
print("Likningen har ingen løsning")
elif d==0:
print(f"Løsning x = {-b/(2*a)}")
else:
sol1 = (-b+math.sqrt(d))/(2*a)
sol2 = (-b-math.sqrt(d))/(2*a)
print("Løsningen er")
print(f"x = {sol1}, og x= {sol2}")
I made this short code to calculate the chances of a success rolling dice, and it worked very well... but not in big numbers. Se the code, I'll explain better below.
def calc_dados(f_sucessos = 1, faces = 6, n_dados = 1):
p_max = ((f_sucessos/faces)**n_dados) #chance de todos
fator = 1
p_meio = 0
for i in range(n_dados-1):
p_meio += (((f_sucessos/faces)**(n_dados-fator) * ((faces-f_sucessos)/faces)**(n_dados-(n_dados-fator))) * n_dados)
fator += 1
p = p_max + p_meio
return p*100
So, ok, it works, why not see how my chances are better in function of adding dice? More the dice, better the chance. So I made this tiny table with pandas:
f_sucessos = 1 # how many faces are success
faces = 2 # faces of the dice
n_dados = 10 # n de dados lançados
suc_list = []
for i in range(0,n_dados): suc_list.append(f_sucessos)
fac_list = []
for i in range(0,n_dados): fac_list.append(faces)
cha_list = []
for i in range(0,n_dados): cha_list.append(calc_dados(f_sucessos, faces, i+1))
df = pd.DataFrame(
{
"n_dados" : range(1,n_dados+1),
"faces" : fac_list,
"sucessos" : suc_list,
"chance" : cha_list
}
)
df
The results were very strange... So I wrote an coin probability table and tested as the coin was an 2 faced dice. The right table is this:
table of right brute force tested results
But if you use my code to create this table the result will be this:
table of the results of my code
Please, anybody can help me to understood why in a certain moment the probabilities just fall when they should be higher? For example:The chance of at least 1 'head' in 4 coins should be 93,75%, but my code says it is 81,25%...
To be honest, I don't get how exactly 'calc_dados' calculate the probability of a success rolling dice.
So instead, I implemented maybe a more naive approach:
First, we calculate the total of possible outcomes: outcomes_total = faces ** n_dados
Second, we calculate the successful outcomes: outcomes_success
At last: p = outcomes_success / outcomes_total
I'm going to add a mathematical proof behind my version of the function a bit later:)
from math import comb
def calc_dados(f_sucessos=1, faces=6, n_dados=1):
assert f_sucessos <= faces
outcomes_total = faces ** n_dados
outcomes_success = 0
f_fail = faces - f_sucessos
for i in range(1, n_dados + 1):
one_permutation = (f_sucessos ** i) * (f_fail ** (n_dados - i))
n_permutations = comb(n_dados, i)
outcomes_success += one_permutation * n_permutations
p = outcomes_success / outcomes_total
return p * 100
These are some testing results
Now my code, based on the images I posted is the sum of all exact chances to find the chance of at least 1 result.
Below the code I will comment the changes.
from decimal import Decimal
def dado(fs=1,ft=6,d=1,ns=1,exato=False):
'''
fs = faces success
ft = faces totals
d = n of dice rolled
ns - n of expected success
exato = True: chance of exact ns events, False: chance of at least ns events
'''
s = Decimal(str(fs/ft))
f = Decimal(str((ft-fs)/ft))
d_int = d
d = Decimal(str(d))
ns = Decimal(str(ns))
p_max = Decimal(str(s))**Decimal(str(d))
fator = 1
po_soma = 0
for i in range(d_int-1):
po = (Decimal(str(s))**(Decimal(str(d))-fator) * Decimal(str(f))**(Decimal(str(d))-(Decimal(str(d))-fator)))*Decimal(str(d))
po_soma += po
if exato == True:
p_max = 0
break
fator += 1
return f'{(p_max + po_soma)*100:.2f}%'
dado(1,2,5,1)
First - not a change, it still dont work well.
Second - I'm using now 'fs' variable to number of faces that means success and 'ns' variable to elaborate how many successes we gonna find, so fs = 1 and ns 2 in 3d6 means 'the chance of find at least 2 of 1 specific face rolling 3 dice'.
Third - I'm using Decimal because I realize that the multiplication of fractions could generate very small numbers and the precision could be affected by this (but it dont solve the initial problem, them Decimal may be quicked out soon).
Fourth - Exato (exact) is now a variable that breaks the loop and send to us just the 'exact value' or the 'at least ns value'. So 'exato=True' means in the last example 'the chance of find exact 2 of 1 specific face rolling 3 dice', a very smaller number.
This is it, my thanks for #Raibek that is trying solve this problem in combinations way, I'll study this way too but if you have an idea about please let me know.
Hello people, it's finally solved!
First I would like to thank Raibek, who solved it using combinations, I didn't realize it was solved when he did it and below I'll tell you how and why.
If you are not following the history of this code, you just need to know that it is used to calculate the probability of getting at least ns successes when rolling d amount of dice. Solution codes are at the end of this answer.
I found out how to solve the problem by talking to a friend, Eber, who pointed me to an alternative to check the data, anydice.com. I quickly realized that my visual check, assembling tables in Excel/Calc was wrong, but why?
Well, here comes my friend who, reading the table of large numbers with 7d6, where the error was already very evident, shows me that although at the beginning the account worked, my table did not have all the possible combinations. And the more possibilities there were, the more my accounts failed, with the odds getting smaller as more dice were added to the roll.
This is the combinations I was considering, in this example on 7d6 case.
In the first code the account was:
successes**factor *failures**factor *d
The mistake is in assuming that the number of possible combinations was equal to d (which is a coincidence up to 3 dice for the tests I did before thanks to factorials of 1 = 1 and factorial of 2 = 2).
Now notice that, in 7d6 example, in the exact 3 block there are some missing possible combinations in yellow:
The correct account for this term of the equation is:
factorial(d) / factorial (failures) * factorial (successes)
With this account we can find out what the chance of exactly n faces rolling is, and then if we want, for example, to know the chance of at least once getting the number 1 in 3d6, we just need to add the chances of getting exactly 1 time, 2 times and 3 times. What the code already did well.
Finally, let's get to the code:
Daniel-Eber solution:
def dado(fs=1,ft=6,d=1,ns=1,exato=False):
'''
fs = faces sucesso
ft = faces totais
d = n de dados
ns - n de sucessos esperados modificados por exato
exato = True: chance de exatamente ns ocorrerem, False: chance de pelo menos ns ocorrerem
'''
from math import factorial
s = fs/ft
f = (ft-fs)/ft
d = d
ns = ns
p_max = s**d
falhas = 1
po_soma = 0
if exato == False:
for i in range(d-1):
po = ( (s**(d-falhas)) * (f**(falhas))) * (factorial(d)/(factorial(falhas)*factorial((d-falhas))))
po_soma += po
falhas += 1
else:
p_max = 0
falhas = d-ns
po_soma = ( (s**(d-falhas)) * (f**(falhas))) * (factorial(d)/(factorial(falhas)*factorial((d-falhas))))
return f'{(p_max + po_soma)*100:.2f}%'
print(dado(1,6,6,1))
Raibek solution:
from scipy.special import comb
def calc_dados(f_sucessos=1, faces=6, n_dados=1):
assert f_sucessos <= faces
outcomes_total = faces ** n_dados
outcomes_success = 0
f_fail = faces - f_sucessos
for i in range(1, n_dados + 1):
one_permutation = (f_sucessos ** i) * (f_fail ** (n_dados - i))
n_permutations = comb(n_dados, i)
outcomes_success += one_permutation * n_permutations
p = outcomes_success / outcomes_total
return f'{(p)*100:.2f}%'
I am a beginner in python and need help to solve the error in my code. I have to write the code from the given flowchart such the user gets the minimum amount of coins in return, but I didn't get the accurate answer, so can you please help me to figure out my mistake and guide me.
[1]: https://i.stack.imgur.com/AUq44.png
Here is my code:
print("amount: ",amount)
payment = input("amount of Payment: ")
payment = float(payment)
change = payment - amount
change = round(change,2)
if change>0:
d = change // 1
change = change - d
if change>0:
q = change // 0.25
i = change // 0.10
n = change // 0.05
change = change - q * 0.25 + i * 0.10 + n * 0.05
n = n+round(change*2,1)*10
print("you got",d,"dollars",q,"quaters,",i,"dimes, and",n,"nickels back in change")
else: print("you got",d,"dollars",q,"quaters,",i,"dimes, and",n,"nickels back in change")
else: print('No change owed')
I won't write the code for you as this will be the best way for you to take benefit from my answer and the help from the community, as well as respecing your work and your classmates'.
There are two main flaws which might cause the problems you are experiencing.
You are calculating all the sub-unities of your currency based on the same value, i.e. the whole amount of change.
q = change // 0.25
i = change // 0.10
n = change // 0.05
The expected output of this section is to have, for a 2 dollars payment:
q = 8
i = 20
n = 40
But if we sum them up togheter, we obtain 8*0.25 + 20*0.1 + 40*0.05 = 6$! How's that?
Pointer: You need to make sure to update your change value, after you have performed the remainderless division.
There is a chance that you get NameError: name 'q' is not defined
if change>0:
q = change // 0.25
i = change // 0.10
n = change // 0.05
change = change - q * 0.25 + i * 0.10 + n * 0.05
n = n+round(change*2,1)*10
print("you got",d,"dollars",q,"quaters,",i,"dimes, and",n,"nickels back in change")
else:
print("you got",d,"dollars",q,"quaters,",i,"dimes, and",n,"nickels back in change")
Taking a look at the above code, assume that change is equal to 0. You are however asking your Python script to print the value of d,q,i and n. But have you initialised these variables in this case?
This is close to a manual division. That means that you should substract the big divisor part before using next divisor. You did int correctly for the dollar part (change = change -d), but failed to do it for the smaller coins. It should be:
if change>0:
q = change // 0.25
change -= q * .25
i = change // 0.10
change -= i * .10
n = change // 0.05
change -= n * .25
Anyway, you are using floating point values for money operations, which is bad because floating point is inaccurate
As soon as you want exact operations in cents, you should either use integer number of cents, or use the Decimal class from the Standard Library.
Python 3. Following code says:
25: RuntimeWarning: invalid value encountered in power
L[i] = (((volume*(10**6))*4*(F**2))/(C*pi))**(1/3) #ft
The error is encountered at L[1,22] to L[1,30] and L[2,15] to L[2,30]
Is it part of the loop? I can copy and paste volume=22 and F=5 and it comes up with the number just fine.
lo = 0.06521 # lbm/ft^3
volume = np.arange(0,31) # M ft^3
lift = volume*10**6*lo # lbm
lift = lift/2000 # ton
C = 0.6 # Cylindrical Coefficient
pi = np.pi
L = np.zeros((3,len(volume)))
for F in range(4,7):
i = F - 4
L[i] = (((volume*(10**6))*4*(F**2))/(C*pi))**(1/3) #ft
You have a scalar overflow problem. Specifying volume as int64 solves the problem.
volume = np.arange(31, dtype=np.int64)
If I rewrite the problem like this:
L = np.zeros((3,len(volume)))
for F in range(4,7):
i = F - 4
D = (((volume*(10**6))*4*(F**2))/(C*pi))
L[i] = D ** (1 / 3)
I can see that at F = 5, I get negative values for some parts of D.
These numbers cube rooted become complex, raising the error.
I am trying to replace the value of 0 with .5, or 1/2 when it has been input initially.
For example, I am trying to have it done before the functions are added. I need to redefine the value of 0 for the input only, and only for the single instance of 0 itself. Not values of 10+.
Here is the project information:
IN = input("Enter IN: ")
N = input("Enter N: ")
NP = input("Enter NP: ")
### These two lines are the part I can't get to work:
if digit == float(0):
digit = float(.5)
###
init = (float(IN)*(float(1)/float(2)))
baselimiter = - (float(N)*(float(1)/float(2))) + ((float(IN)*
(float(1)/float(2))) * (float(NP)*(float(1)/float(2))))
lset = init + baselimiter
limitconverto1 = (lset / init) * (init / lset)
infalatetoinput = (((init * float(IN))) / init )
limit = limitconverto1 * infalatetoinput
result = limit
print(result)
So here is a code that does what you want.
Now to be honest, it works but I don't understand WHY you do that. You do a bunch of weird calculations like multiplying and dividing by the same number...
IN = float(input("Enter IN: "))
N = float(input("Enter N: "))
NP = float(input("Enter NP: "))
# The part that interests you.
IN = 0.5 if IN == 0 else IN
N = 0.5 if N == 0 else N
NP = 0.5 if NP == 0 else NP
init = IN * 1/2
baselimiter = -N*1/2 + IN*1/2*NP*1/2 # Removed all the superfluous float() and parenthesis.
lset = init + baselimiter
limitconverto1 = (lset / init) * (init / lset) # That's just always 1. What is intended here?
infalatetoinput = (((init * float(IN))) / init ) # That's always IN. Same question?
limit = limitconverto1 * infalatetoinput # Equivalent to 1 x IN...
result = limit
print(result) # Your result is always IN...
You can use one-liners when you declare the variables:
IN = (float(input("...")) if float(input("...")) != 0 else .5)
One-liners are for loops or if statements (or both) that are in one line instead of multiple lines when declaring variables. They can only be used for the declaration of variables. The one-liner I suggested is would be in multiple lines:
if float(input("...")) != 0:
IN = float(input("..."))
else:
IN = .5 #You don't need to say float(.5) since .5 is a float anyway.
More about One-Liners: One-Liners - Python Wiki
I hope this edit of my previous answer fully answers your question, for more clarification I will be available on the comments