repetitive value assignment in a while loop, Python - python

Please look at following while loop code written in Python:
x=25
epsilon=0.01
high=max(1.0,x)
low=0.0
*ans=(low+high)/2.0*
while abs(ans**2-x)>=epsilon:
if ans2>x:
high=ans
else:
low=ans
*ans = (high + low)/2.0*
print("ans:",ans,)
This is a guess loop (exhaustion), it should find the approx for square root of a positive number within the margin error on 0,01.
But I cant understand why we must define ans (ans=(low+high)/2.0) the second time, first before the loop and then again in the loop. Could someone tell me what purpose the second definition have since im seeing the first one being enough?
Thanks
Arif

It's because you need to perform that calculation on each iteration of the loop including the very first iteration. Since your while test is the very first part of the loop, you need to do it once before the loop starts.
Here's a way to do it with just one statement:
while True:
*ans = (high + low)/2.0*
if abs(ans**2-x)>=epsilon:
break
if ans2>x:
high=ans
else:
low=ans

Related

Is this possible Else condition to work after break & trying to change for loop value?

Create random numbers of 150 and take a uniform sample of 78
import numpy as np
population_data=np.random.randint(1,600,150) # 150 random numbers(integers) genereated
sample_data=[]
sample_lenth=78
p=30/len(population_data)
for i in range(1,len(population_data)):
if np.random.random() <=p:
sample_data.append(population_data[i])
print(i,len(sample_data))
if sample_lenth==len(sample_data):
break;
else:
i=10 # (basically wants to change the i value lower that for loop keep running )
print(i)
print(len(sample_data))
print(sample_data)
for loop is running still 150 which is valid and I cant add more range in for loop as if i>150 then sample_data.append(population_data[i] ) will be out of range.
What I want to achieve is:
if sample_lenth==len(sample_data): then break else change the i value to any in between 1-150 that loop continues
Any help !!
I'm afraid the for...else construct has nothing to do with what you are looking for.
The else clause is executed at most once, after the for loop has finished.
See e.g. https://book.pythontips.com/en/latest/for_-_else.html
You cannot change the i variable inside a for loop. Probably you want to use a while loop. See e.g. How to change index of a for loop?

How to change initial condition in while loop

I am entering a while loop with a specific initial condition (m=0). Inside the while loop I have a for loop which needs to break if a spec. condition is reached, here if my growth rate is >= 20%.
If this condition is reached I want to leave the for loop and use i to set the new m. Then I want to do a new for loop and again leave the loop if the condition is reached and use the new i for m.
I tried with m+=i but this sums up the i's, which I don't want. I want the every new i is used for m. Please find below the code
nvdia=pd.read_csv(r"/NVDA.csv",sep=",").round(1)
nvdia["Date"]=pd.to_datetime(nvdia["Date"])
nvdia=nvdia.set_index(nvdia["Date"])
nvdia=nvdia.drop("Date",1)
nvdia=nvdia.loc["2017-07-01":"2018-07-01"]
#nvdia["Close"].plot()
m=0
i=0
while m<len(nvdia.index):
m+=i ###This is what I use but it is wrong. If I use i=m the loop is goes infinity, which really is strange
for i in range(m,len(nvdia.index)):
percentage_growth=100*(nvdia["Close"].values[i]/nvdia["Close"].values[m]-1)
if percentage_growth>=20:
break
#zmf: Thank you it helped. However I needed to add an additional break statement to leave the while loop, since my condition m
In case someone might have one day same/similar issue, here is the solution
m=0
while m<=len(nvidia.index):
for i in range(m,len(nvidia.index)):
percentage_growth=100*(nvidia["Close"].values[i]/nvidia["Close"].values[m]-1)
if percentage_growth>=20:
m=i
print(m,percentage_growth)
break
else:
percentage_growth=100*(nvidia["Close"].values[i]/nvidia["Close"].values[m]-1)
if i+1==len(nvidia.index):
break

While loop automatically updates previous list values

I'm trying to implement the SOR algorithm in Python 3.X in order to solve an electrostatics problem. But, when inside the while loop, the break condition (relative error between previous and current iteration) appears to be fulfilled in the first iteration, which is certainly not correct. When troubleshooting the problem I found that the previous and current iterations have matching values:
def solve_laplace_SOR(w,tolerance,cant_puntos,step,volt):
phi_vec=np.zeros(cant_puntos)# zero seed vector, stores previous iteration
phi_vec_k1=np.zeros(cant_puntos) #Stores current iteration
b_vec=load_ind_term(volt,cant_puntos) #independent term
E_vec=np.zeros(cant_puntos) #Electric field
R_error=100 #Initializes relative error condition so as to enter the loop
i=0 #counts iterations made
#Initializes boundary conditions
phi_vec_k1[0]=volt/2
phi_vec_k1[cant_puntos-1]=-volt/2
while R_error > tolerance:
phi_vec=phi_vec_k1[:] #Stores previous value as a copy, I checked this using id() function
phi_vec_k1[1]=((b_vec[0]-phi_vec[2])/(-2)-phi_vec[1])*w+phi_vec[1]
for x in range(2,cant_puntos-3):
phi_vec_k1[x]=((b_vec[x-1]-phi_vec[x+1]-phi_vec_k1[x-1])/(-2)-phi_vec[x])*w+phi_vec[x]
E_vec[x]=(-(phi_vec_k1[x+1]-phi_vec_k1[x-1])/(2*step))
pass
phi_vec_k1[cant_puntos-2]=((b_vec[cant_puntos-2]-phi_vec_k1[cant_puntos-3])/(-2)- phi_vec[cant_puntos-2])*w+phi_vec[cant_puntos-2]
E_vec[cant_puntos-2]=(-(phi_vec_k1[cant_puntos-1]-phi_vec_k1[cant_puntos-3])/(2*step))
E_vec[1]=(-(phi_vec_k1[2]-phi_vec_k1[0])/(2*step))
R_error=np.linalg.norm(np.array(phi_vec_k1)-np.array(phi_vec),1)/np.linalg.norm(phi_vec_k1,1)
i+=1
print(phi_vec_k1) #This outputs the same values
print(phi_vec)
pass
return E_vec
When setting an always true break condition, the function converges to expected values. Since i'm new to python and programming in general, i can't seem to find the reason for the unwanted update. I really hope you can, thanks very much!

using copy in iterations

something is not going right in my code below. I have a big for loop which handles some math. But in the for loop the following guys contribute to the end result.
say:
for i in range(N):
# The math goes here.
sumrfactor=0.0
for k in R_factor:
sumrfactor += k
# print(sumrfactor)
Rfactor_sum=0
for n in signal:
Rfactor_sum +=n
#print(Rfactor_sum)
r_factor = sumrfactor/Rfactor_sum
rfactor = [r_factor.copy()]
export = open('note.txt','w')
for n in rfactor:
export.write(str(n))
For each iteration I want to copy r_factor I need it for some further analysis, so I am expecting to get N number of r_factor at the end of the big for loop. But for some weird reason I keep getting the final value at the end of the mighty for loop. i.e. I get one value instead of an array. Please guys I need your help with this issue, I have no idea where the problem is at. When I open the note file there is always a single figure which obviously does not look right. Thanks guys in advance!
Your problem is that you don't append the value to the list. Change the line rfactor = [r_factor.copy()] to this:
rfactor.append(r_factor)

Python generate random steps for range function in each iteration of a for loop

I am trying to split a string into small chunks of random sizes. For example,
string = 'qwertyuiopp' into ['qw','e','rty,'u','iopp']
for record in SeqIO.parse(args.fasta_file , "fasta"):
step = 200
for i in range(0, len(record),step):
oline = ">"+record.id+"_"+str(i+1)+"\n"
ofname.write(oline)
step = random.randrange(200,2000)
if len(record.seq[i:i+step]) >= 200:
oline= str(record.seq[i:i+step])+"\n"
ofname.write(oline)
i=i+step
else:
oline= str(record.seq[i-200:])+"\n"
ofname.write(oline)
i=len(record)+1
I figure the problem is that the step in range function remains constant(200) inspite of modifying the value of step using randrange. but I dont know how I should go about this. Thank for any help.
range function creates a list as soon as the for loop is encountered. It does not get evaluated for every iteration.
You can use a while loop for this purpose.
import random
step = 1
count = 0
while count < len(record):
print count
step = random.randint(1, 5)
count += step
The range function does not remember how it got the values it was constructed from. When you call range(0, len(record), step) that creates either the range object range(0, 1000, 200) (Python 3.x) or the list [0, 200, 400, 600, 800] (Python 2.x). Either way, changing step later isn't going to change anything.
You could build a custom iterator that that lets you reset its step, or one that changes its step and iterates (start, end) or (start, step) pairs. But that may be a little advanced for you.*
In that case, when you can't find or write an iterator to loop over, you have to go to a while loop, and update your loop variable manually.
It's worth noting that you're already trying to update your loop variable manually, with that i = i + step. That's usually a bad idea inside a for loop—but inside a while loop, it's exactly what you want. So really, just change this line:
for i in range(0, len(record),step):
… to these two lines:
i = 0
while i < len(record):
There are other problems in your code that you have to fix (including at least two IndentationErrors), but you can fix them once you get past this.
One last thing: Whether you've got a for loop or a while loop, if you want to break out early, the way to do it is a break statement, not by trying to change the loop conditions so the next test will fail. So, replace that i=len(record)+1 at the end with break as well.
* Also, the obvious implementation for such an iterator would be the same kind of while loop anyway…

Categories

Resources