问题
I have created a long code, consist of multiple lists inside for-loops. There are nothing wrong with calculation.It does obtain results as it is expected to. The code and construction of lists work fine. The problem is when it runs, I have defined a break when a certain condition is matched. But it does not break at first run, continues and run through all values within range function of first loop. I want to achieve to return a true value, when the condition is matched, and stops and will not keep growing according to range values in first loop.
I would explain how the code would work!
The code: First part is consistent and are inputs
import math
import numpy as np
Ned = -500
fcd = 20
fyd = 435
E = 2e5
h = 200
cb = 35
ct = 35
ca = 35
b= 150
y = 12
d = h - cb
ds = ct
a = 25
yb = 8
ecu = 0.0035
rebarnumber = math.floor((b-(2*cb+2*yb+y))/a)
PI_Y2_4 = int(math.pi/4*(y)**2)
disc = []
dis = []
Asi = []
Asci = []
Esc = []
Esci = []
Sc = []
Sci =[]
#############################
# Calculation starts here
#############################
for n in range(0,10): # <------- First for-loop
cbb = cb + yb + y/2
ctt = ct + yb + y/2
if 0 < n <= rebarnumber:
Asi.append(PI_Y2_4)
dis.append( h - cbb)
Asci.append(PI_Y2_4)
disc.append( ctt )
if rebarnumber < n <= (2 * rebarnumber):
Asi.append(PI_Y2_4)
dis.append( h - cbb - ca)
Asci.append(PI_Y2_4)
disc.append(cbb + ca)
if (2*rebarnumber) < n <= (3 * rebarnumber):
Asi.append(PI_Y2_4)
dis.append( h - cbb - 2*ca)
Asci.append(PI_Y2_4)
disc.append(cbb + 2*ca)
if (3*rebarnumber) < n <= (4 * rebarnumber):
Asi.append(PI_Y2_4)
dis.append( h - cbb - 3*ca)
Asci.append(PI_Y2_4)
disc.append(cbb + 3*ca)
if (4*rebarnumber) < n <= (5 * rebarnumber):
Asi.append(PI_Y2_4)
dis.append( h - cbb - 4*ca)
Asci.append(PI_Y2_4)
disc.append(cbb + 4*ca)
if (5*rebarnumber) < n <= (6 * rebarnumber):
Asi.append(PI_Y2_4)
dis.append( h - cbb - 5*ca)
Asci.append(PI_Y2_4)
disc.append(cbb + 5*ca)
if (6*rebarnumber) < n <= (7 * rebarnumber):
Asi.append(PI_Y2_4)
dis.append( h - cbb - 6*ca)
Asci.append(PI_Y2_4)
disc.append(cbb + 6*ca)
if (7*rebarnumber) < n <= (8 * rebarnumber):
Asi.append(PI_Y2_4)
dis.append( h - cbb - 7*ca)
Asci.append(PI_Y2_4)
disc.append(cbb + 7*ca)
for i in range(0,len(dis)):
Esc.insert(i, dis[i])
Esci.insert(i, disc[i])
Sc.insert(i, dis[i])
Sci.insert(i, disc[i])
for x in np.linspace(1,h,10000): # <-------- Second for-loop
for k, _ in enumerate(Esc):
try:
if x < dis[k]:
Esc[k]=( ecu/x*(dis[k]-x) )
else:
Esc[k]=(- ecu/x*(x-dis[k] ) )
if x < disc[k]:
Esci[k]=( -ecu/x*(x-disc[k]) )
else:
Esci[k]=(- ecu/x*(x-disc[k]) )
except (ZeroDivisionError, RuntimeWarning):
Esc[k]=( 0 )
Esci[k]=( 0 )
for k, _ in enumerate(Sc): # <-------- Third for-loop
ss = Esc[k]*E
if ss <= -fyd:
Sc[k]= -fyd
elif ss >= -fyd and ss < 0:
Sc[k]=ss
else:
Sc[k]=min(ss,fyd)
for k, _ in enumerate(Sci):
sci = Esci[k]*E
if sci <= -fyd:
Sci[k]= -fyd
elif sci >= -fyd and sci < 0:
Sci[k]=sci
else:
Sci[k]=min(sci,fyd)
FS = 0
FSC = 0
for a, _ in enumerate(Sc):
FS += Sc[a]*Asi[a]
FSC+=Sci[a]*Asci[a]
MS = 0
MSC = 0
for m, _ in enumerate(Sc):
MS += Sc[a]*Asi[a]*(dis[m]-h/2)
MSC+= Sci[a]*Asci[a]*(h/2-disc[m])
Nrd = 0
Mrd = 0
Nrd = int((-0.8*x*b*fcd+FSC+FS)/1000)
Mrd = (0.8*x*b*fcd*(h/2-0.4*x)+MS-MSC)/1000000
if 0 <= (float(Nrd) - Ned) <= 1:
print(Nrd, x, Asi)
break
break
How does it work?
First for-loop creates a list with index 0 i.e. [value1]
, second for-loop makes a x value increment ( range), third for-loops creates lists depend on first created list [value1]
. then Nrd
value determines based on increment of x values. if condition 0 <= (float(Nrd) - Ned) <= 1:
is met, then the calculation would stop and return Nrd
value. if not matched, it goes back and take index 1 from first for-loop, [value1, value2]
is created, again reach to Nrd if condition is met, would break otherwise continues until it is matched.
My problem is when the code runs, I get those outputs.
Nrd x Asi
---------------------------------------------------
-499 181.84938493849384 [113]
-499 162.36533653365336 [113, 113]
-499 147.3990399039904 [113, 113, 113]
-499 137.48784878487848 [113, 113, 113, 113]
-499 130.72117211721172 [113, 113, 113, 113, 113]
-499 126.10391039103911 [113, 113, 113, 113, 113, 113]
-499 122.7006700670067 [113, 113, 113, 113, 113, 113, 113]
-499 120.01390139013901 [113, 113, 113, 113, 113, 113, 113, 113]
-499 119.71537153715371 [113, 113, 113, 113, 113, 113, 113, 113, 113]
Above outputs are all true mutiple solutions. But I want to stop ( break) by first match, instead of giving all solutions.
I have used return True
, but it is not really working here, when it complains of being out of function.
Second issue here is second for-loop for x in np.linspace(1,h,10000):
I really want to run it with many decimals to get a best result, but it slows down and takes long time to calculate. Is there a way to speed up?
Perhaps defining above codelines into functions would work more efficient.
回答1:
The easiest and most straight-forward solution is to move all of your code inside a function
def calculate_results(...args...): # Bad name, use a more suitable one
...
for n in range(0, 10): # <------- First for-loop
...
for x in np.linspace(1,h,10000): # <-------- Second for-loop
...
if 0 <= (float(Nrd) - Ned) <= 1:
return Nrd, x, Asi
and then call the function afterwards
Nrd, x, Asi = calculate_results(...)
print(Nrd, x, Asi)
Use a function name that really describes the essence of what the functions is doing and do only that single thing within the function. Then the return
statement makes it clear that this task is now done.
来源:https://stackoverflow.com/questions/53548289/break-and-return-inside-multiple-for-loops-with-conditional-statement