How to create a while loop with tolerance - python

I'm trying to do some control engineering where I start with a certain value, for example, x = 5 and in the end, it should return x. The goal, in the end, is to find a value for x, where x (beginning) == x (end).
I was thinking about creating a while loop and just adding or subtracting a certain stepsize on x(beginning) till it reaches equilibrium. However, I want some tolerance in my while loop. Like x(beginning) ==x(end)+0.1 would also be fine.
I don't know how to create this in Python and I'm not sure whether this is even the right way to accomplish this

You could do something like this:
# in this example, x is the beginning value, y is the end value
x = 5
y = 10
tolerance = 0.1
while True:
if abs(y-x) <= tolerance:
break
# put your code here
x += 1 # or something else

I think what you are looking for is math.isclose(). With that you can specify both a relative and an absolute tolerance limit.
isclose(a, b, rel_tol=1e-9, abs_tol=0.0)

Related

Python script that increases a number by a percent and then with a new number till goal

I found this problem and wanted to try to execute, but got stuck:
Compile a program that allows you to determine how many days will be enough for 200 something if consumed on the first day 5 tons, but every next day 20% more than the previous day.
In Python, using loop operators, lists and
functions.
I tried with the def function, but I don't know if it's correct and I don't know how to get it so that when it increases by 20%, the new number increases by 20%, so all the time with new numbers until it reaches 200
def day():
x=5
x += (x * 20/100)
print(x)
day()
it is just a half, i know.
Declaring Needed Variables
numberOfDays = 0
totalTons = 200
dayTonsUsed = 5
Consuming the tons and modifying the variables
while (totalTons > 0):
totalTons -= dayTonsUsed
dayTonsUsed *= 1.2 # Adding extra 20% of consumption for the next day
numberOfDays += 1
Getting total days
print(f"Number of days needed {numberOfDays} days")
You are calling the function a single time, basically X is incrementing once and then not being referenced again. To increment X until you reach a value >= 200, you would need to use a while loop. Code could look like this:
x = 5
dayscount = 1
while x < 200:
print(x)
print(dayscount)
dayscount = dayscount + 1
x = x * (1+(20/100))
you dont necessarily need to define within a function either, but if you did, you would need to define x outside the function and make it a global variable.
The solution which you're trying to implement, is very close, but you're not actually adding the values from day. You want something like the following:
def day(x):
return x + (x * 20/100)
x = 5
currentSum = x
day = 1
while(currentSum < 200): # Loop until the amount consumed is more than 200
x = day(x)
currentSum += x
day += 1
print(day)
Note, there is a faster mathematical solution, but it is not necessary for this problem since all the numbers are fairly small.
with recursion it could be done this way:
def day(n, x=5):
return 1 + day(n-x, x*1.2) if n>0 else 0
day(200) # 13

How to iterate through random or specific values in a range? in a non sequential way, in Python

The way Python iterates through a range in a for loop is given the range from (0 to n) it will do the operations first for 0, then for 1, 2... until it finishes in n, completing the for loop. Am I correct?
I have a working code that needs to be optimized for speed, it looks something like this:
Phi = np.arange(0.00005, 0.000101, 0.000001)
Strip_depth = 0.001
for angle in Phi:
Neutral_axis_depth = np.arange(150, 160, 0.0001)
for xn in Neutral_axis_depth:
Sn = int(xn / Strip_depth)
x = [0] # strip center coordinates
for i in range(0, Sn - 1):
x.append(x[i] + Strip_depth)
...
# and the a lot of calculations that will eventually result on C and T
...
comparison_parameter = 0.1
dif = T - C
if comparison_parameter > dif > -comparison_parameter:
# here I need to print the corresponding values of Phi, Xn , C, T and dif in a table
# but that's another question...
My problem is that I need a high precision on the result and for that I have to modify either the "strip_depth", or the "Neutral_axis_depth" np.range step, which will cause more operations and will take more time.
I thought that instead of performing the iterations in Xn in a sequential way I could save time by picking a random value in the range and continuing depending on the value, for example:
if dif is negative I can neglect the values of the range from that point forward
if dif is positive I can neglect the values of the range before that point
and repeat this while dif > comparison_parameter. This way the operation is not done Sn times, only a few. Another option would be to decide the values for the iteration, like 1/3rd of the range, 2/3rd of the range, and then 1/3rd of the "remaining range" or something like that.
In a way I'm defining a new range with these steps. Either way I don't know how to do this...thanks in advance for the help.
I dont exactly follow, but it seems like range() isn't the best choice for this use case. If you want to adjust the chosen value as needed, then use while + custom variable adjusted manually:
i = 0 # initiate the custom variable
while i < Sn - 1: # instead of range()
# under normal circumstances increase `i` in each loop by 1
i += 1
# if specific conditions are met, increase the value as needed
if dif < 0:
i += 50

How do you reach a certain value for two variables at the same time while iterating?

I have 2 variables that contain the amount of steps I want to do in each direction.
# could be any values (including being the same amount)
x_steps = 300
y_steps = 200
Now I want to draw a line slowly by moving both the current x-coordinate and y-coordinate.
The important thing is, that I want to finish both directions at the same time, so it looks like a straight line.
This means, that in some iterations I need to do multiple steps for (in this case) x.
for x in range(y_steps):
# do step in y direction
# do step in x direction
if certain_condition:
# do another step in x direction
I'm having trouble coming up with such a condition, how do I achieve this?
You could do this by keeping track of the number of steps and using those numbers in the condition:
i, j = 0, 0
for x in range(y_steps):
# do step in y direction
j += 1
# do step in x direction
i += 1
if i/j < x_steps/y_steps:
# do another step in x direction
i += 1
To simplify this, you can use x (maybe rather call it y, as it runs through the y steps) directly instead of j, or use a while loop.

Python: "If" function

This is probably really simple but I can't figure it out.
I have a bunch of lists and I want to call certain lists if they are in the range equal to a value x and any number between x-5 and x +5. i.e. x-5,x-4,x-3,x-2,x-1,x,x+1,x+2,x+3,x+4 and x+5.
At the moment I have
if sum(listname[i])==x:
if sum(listname[i])==x-1:
if sum(listname[i])==x-2:
etc
How can I do it so that it is combined in one "if" function.
I've been thinking on the lines of something like:
if sum(listname[i])==x-5>=x>=x+5:
or
if sum(listname[i])==x or x-1 or x-2 ".. etc":
but neither work.
Can anybody shine some light on this?
A scenario like if sum(listname[i])==x or x-1 or x-2 ".. etc": (which is not valid python) is usually solved with if value in range(start, stop, step):
So you would write:
if sum(listname[i) in range(x-2, x):
# Code for this case here...
Do you simply mean
if x-5 <= sum(listname[i]) <= x+5:
...
...
It looks like you want to check if the sum of the list is between x - 5 and x + 5. To put it in one if statement is simply:
s = sum(listname[i])
if s >= x - 5 and s <= x + 5:
# do stuff
From what I understand from your question. You what to check that whether sum(listname[i]) is between (x-5, x+5)
You can do this in a single if assuming x is a possitive value:
if (sum(listname[i]) >= (x - 5)) and (sum(listname[i]) <= (x+5))

Python While Loop Square

I am a beginner at Python and I'm trying to use a while loop to sum up all of the squared n values in a given n value range.
Code:
def problem2(n):
x = 0
y = 0
while x < n:
y = (n**2)+y
x+=1
return y
For some reason, this equation returns the input number cubed.
Can someone explain why this happens and how to fix it?
You need to perform the ** on x, the value that is being incremented:
def problem2(n):
x = 0
count = 0
while x < n:
count += pow(x, 2)
x += 1
return count
You keep squaring the same number n, instead of the one being incremented x.
def sum_of_squares(n):
sum = 0
for x in range(0, n):
sum += x*x
return sum
You also don't really need the while loop, avoiding having to manually keep track of which variable is the counting variable and which one is the result variable (which is what you are confusing, as explained e.g. by #Ajax1234 in their answer).
It is a lot more Pythonic to use the built-in function sum, a generator expression and range:
def problem2(n):
return sum(x**2 for x in range(n))
This would be a lot more readable and better (unless of course you are being forced to use while).
Looks good. You're almost there.
It makes it the cube root because you add y to (n**2) everytime. Because you code runs until x !< n it runs n times. That means that you add n**2 to n**2*n.
That means that it gives 1(n**2)*(n-1)(n**2) which equals n(n**2) = n**3
Hope this was clear enough.

Categories

Resources