0

This one is a big mystery to me.

I have a python script that consists entirely of the pasted code:

def onedutilfun(x):
    u = -( (x/2)**(1/2) + 2*((1-x)/3)**(1/2))
    return u

test = onedutilfun(0.01)
test2 = onedutilfun(99)

print(test)
print(test2)

I am running this code in Spyder. I have an installation of Spyder that runs python 3.6 and another that runs 2.7. If I run this in 2.7, it returns -3, regardless of what value I pass it. I've tried various conversions to floats (u and x already are floats, and Spyder agrees with me), to no avail.

If I run this same code in python 3.6, it works fine, returning exactly what it should return. What might be going on? I realize one solution would be to use newer python, but I need to provide code that runs in 2.7.

The value 99 returns a complex number, fyi.

I've pasted the code into Google's search bar, and the graphed function (over the function's domain in the real number system) looks good, too.

I have successfully used ** before in my copy of Python 2.7, and used it in cases where it can return complex values, or where it might throw an error if it returns complex unless I tell it to return a complex number.

Besides wanting working code, I would really enjoy an explanation of what is happening with my code. Thank you.

Jimmy
  • 337
  • 4
  • 13
  • 1
    `x` may be a float, but in Python 2.7 - `1/2` == 0... so anything involved with that `** 0` is 1 - ergo, your function in 2.7 is effectively: `return -(1 + 2*1)` which is the `-3` you're getting. – Jon Clements Feb 24 '18 at 18:51
  • Probably a simple fix is to use `** 0.5` instead of `1/2`... (or, use the far more explicit `math.sqrt`) (or even put a `from __future__ import division` in the top of the module) – Jon Clements Feb 24 '18 at 18:56
  • Thank you. That answer makes sense; didn't realize this was the case with integer division in python 2.7. – Jimmy Feb 24 '18 at 18:57

1 Answers1

1

In python 2, integer division with / always returns integers, rounded down, so 1/2 == 0. Anything to the 0 power is 1, so your function returns -(1+2).

There are a number of ways to correct your code, but probably the simplest would be

def onedutilfun(x):
    u = -( (x/2.)**(1/2.) + 2*((1-x)/3.)**(1/2.))
    return u

Note that every division now has a number with . after it, which indicates a float instead of an int. However, this limits the range of the function: it can no longer accept numbers outside the range [0, 1], at least in python 2. If you need support for real or complex results, you modify it just a bit:

def onedutilfun(x):
    x += 0j # ensure x is complex
    u = -( (x/2.)**(1/2.) + 2*((1-x)/3.)**(1/2.))
    if not u.imag:
        return u.real
    return u

This will give real-numbered values (instead of, eg. -1.316496580927726-0j) where possible and complex values otherwise.

Nathan Vērzemnieks
  • 5,495
  • 1
  • 11
  • 23