0

So say I have the lower value and an upper value of an integral that's from the user input. I ask for the lower limit first then I check for its validity. Then in order to compare the value of my upper limit with my lower I made a nested function, so that I can also ask for user input of the upper limit, checks its validity and making sure that my upper limit is bigger than my lower(cuz u know integration), shown with the code below.

def LowLimCheck():
    while True:
        try:
            a = float(input("Please enter the lower limit of the integral: "))
            break
        except ValueError:
            print("Invalid input. Please enter a number.")
    print("You have chosen the lower limit: ", a)      

    def UppLimCheck():
        b = -1
        while b <= a:
            while True:
                try:
                    b = float(input("Please enter the upper limit of the integral: "))
                    break
                except ValueError:
                    print("Invalid input. Please enter a number.")

            if b <= a:
                print("The upper limit must be bigger than the lower limit!")
        print("You have chosen the upper limit: ", b) 
        return b           
    UppLimCheck()  
    return a

Now this is all well and fine until I actually need to use the values a and b because I need to put those values into an integral that I've set up. It's basically a general integral made by the Simpson's rule, that is trivial to get into right now. So I defined the function as:

def simpsonsRule(func, a, b, N):

    <insert code here>
    <insert code here>

    return d

OK so my function basically lets user insert any arbitrary function, the upper limit(a), the lower limit(b) and N(number of strips in Simpson's rule) and it spits out d which is the evaluation of the integral of the arbitrary function above by Simpson's Rule. My problem now is that when I'm trying to print the answer, I can take the variable a out and put in into the integral but I can't take the variable b out because it's in a function! For example if I now print the integrated value(say in this case of sin(x) and N = 20)

print(simpsonsRule(lambda x:np.sin(x), a, b, 20)

So I know that a and b values are local within their own functions. Now for the value of a I could easily just do this to get the value a

k = 0 #initialising the variable
k = LowLimCheck()
print(simpsonsRule(lambda x:np.sin(x), k, b, 20)

Because since k invokes LowLimCheck() which returns the value for a which I can put into my function. But how can I get my value of b which is nested within the first function? I want to use b basically. Is there a way round this?

Apologies for the lengthy question and thanks in advance!

user3613025
  • 373
  • 3
  • 10
  • 1
    Rather than to nest UppLimCheck in LowLimCheck, a better alternative might be to call them in serial... like `a = LowLimCheck()` then b = UppLimCheck(a). Then you have a more readable structure, less variable scope to keep track of, and you avoid this problem altogether. – Joshua R. Dec 27 '17 at 21:59

1 Answers1

1

You can return a tuple from LowLimCheck():

def LowLimCheck():
    ...
    b = UppLimCheck() 
    return (a,b)

then unpack them when calling LowLimCheck()

a, b = LowLimCheck()

UPDATE:

In the most direct answer to your question, LowLimCheck() becomes:

def LowLimCheck():
    while True:
       try:
            a = float(input("Please enter the lower limit of the integral: "))
            break
        except ValueError:
            print("Invalid input. Please enter a number.")
    print("You have chosen the lower limit: ", a)      

    def UppLimCheck():
        b = -1
        while b <= a:
            while True:
                try:
                    b = float(input("Please enter the upper limit of the integral: "))
                    break
                except ValueError:
                    print("Invalid input. Please enter a number.")

            if b <= a:
                print("The upper limit must be bigger than the lower limit!")
        print("You have chosen the upper limit: ", b) 
        return b     

    b = UppLimCheck()   # Storing the b
    return (a,b)        # Passing b out with a in a tuple

then call

a, b = LowLimCheck()

finally,

print(simpsonsRule(lambda x:np.sin(x), a, b, 20)

ALTERNATIVE SOLUTION (more substantial changes, but better code structure - as described in the original comments; flatter, more readable, fewer scope considerations):

def LowLimCheck():
    while True:
        try:
            a = float(input("Please enter the lower limit of the integral: "))
            break
        except ValueError:
            print("Invalid input. Please enter a number.")
    print("You have chosen the lower limit: ", a)      

    return a

def UppLimCheck(a):
    b = -1
    while b <= a:
        while True:
            try:
                b = float(input("Please enter the upper limit of the integral: "))
                break
            except ValueError:
                print("Invalid input. Please enter a number.")

        if b <= a:
            print("The upper limit must be bigger than the lower limit!")
    print("You have chosen the upper limit: ", b) 

    return b  

then:

lowLim = LowLimCheck()
upLim  = UppLimCheck(lowLim) # pass in lowLim as an argument

print(simpsonsRule(lambda x:np.sin(x), lowLim, upLim, 20)
Joshua R.
  • 2,282
  • 1
  • 18
  • 21
  • Is the UppLimCheck() in this case defined outside LowLimCheck()?When I use `a, b = LowLimCheck()` do I then do `print(simpsonsRule(lambda x:np.sin(x), a, b, 20)` ? This might be a bad question but sorry I'm still new to this. – user3613025 Dec 28 '17 at 16:13
  • No problem, @user3613025. See the update in the answer above. – Joshua R. Dec 28 '17 at 20:05
  • Last question, I need to let users to enter the limit of integration of their choice. How can I allow my program such that if they type "pi/2" or "pi/6" or just any fraction of pi, so that it can recognise and translate into numpy's value of "pi/2" or "pi/2"? – user3613025 Jan 28 '18 at 16:00
  • Hi @user3613025, this is a bit unrelated question and quite a large topic of its own. You might look for posts on Python math parsers. One "quick and dirty" approach would be to use Python's `eval` function. 1) `import numpy as np` 2) `pi= np.pi` and 3), do something like `userVal= eval('userText')`. The Python `eval` function executes the given string as code and returns the result. So `eval('pi/2')`, in this case, returns ~1.57. You *are* letting your users execute arbitrary code. It may be wrong, so *try/except* to handle syntax errors; it may be malicious- so watch out for hackers! – Joshua R. Jan 28 '18 at 18:01
  • BTW, you might accept this answer if it addressed your question. Cheers! – Joshua R. Jan 29 '18 at 02:14