Jstuff
Jstuff

Reputation: 1342

Python not computing equation correctly

I'm trying to write a simple program to plot x vs y. However, it does not seem to be computing the correct value ofy.

For instance in the first case when x = -1 the value of e^(x^2/2 - x) -1 should be 3.48, but instead it is returning 1.

The other error I have is it doesn't seem to be plotting x vs y, but instead a separate line for each value of x.

import numpy as np
import math
import matplotlib.pyplot as plt

x = np.arange(-2, 2)
y = np.arange(-2, 2)

for i in range(-3, 3):
    y[i] = math.exp(( x[i]^2/2 ) - x[i])-1

print x, y
plt.plot([x, y])
plt.show()

Upvotes: 1

Views: 160

Answers (4)

Waylon Flinn
Waylon Flinn

Reputation: 20257

The built in numpy array operations are perfect for this.

This is the line you want:

 y = np.exp(np.power(x, 2)/2 - x) - 1

Full code then becomes

import numpy as np
import math
import matplotlib.pyplot as plt

x = np.arange(-2, 2)

y = np.exp(np.power(x, 2)/2 - x) - 1


print(x, y)
plt.plot(x, y)
plt.show()

(Note, the plot statement is also changed here)

Details

If you start to write a loop when working with numpy, look for another way. Vector operations can be much faster (sometimes several orders of magnitude) than the corresponding python code, that's why people love it. Many of the basic operations (+, -, *, /, **) are even overloaded. Check the last item in the References section for more info.

References

Upvotes: 3

taleinat
taleinat

Reputation: 8711

The problems in your code:

  • you used the xor operator ^ instead of the exponentiation operator **
  • you didn't pass the lists of values to plt.plot() properly
  • by dividing an integer by an integer, you were actually doing integer division, i.e. 3/2 -> 1
  • you accidentally rounded all of the results into integers by assigning to y[i], because y was made as an array of integers (as @efirvida explained, this is because np.arange() infers the type from the given values)
  • the range of indexes you were iterating over was very unclear, lots of room for mistakes there... (not actually a bug)

This works on Python 3.4:

import numpy as np
import math
import matplotlib.pyplot as plt

x = np.arange(-2, 2)
y = np.ndarray(len(x), float)

for i in range(len(x)):
    y[i] = math.exp(( (x[i]**2)/2.0 ) - x[i])-1
print(x, y)
plt.plot(x, y)
plt.show()

Upvotes: 2

tzaman
tzaman

Reputation: 47800

^ isn't the exponentiation operator in Python, it's bitwise-XOR. You need to use ** instead. Also, if you're plotting functions over arrays, it's much cleaner to write your function directly and apply it via vectorize.

Also, if you're using Python2.7 you should add from __future__ import division to get true (floating point) division, otherwise x/2 will use integer division instead.

from __future__ import division
import math
import numpy as np    
import matplotlib.pyplot as plt

f = np.vectorize(lambda x: math.exp((x**2/2) - x) - 1)
x = np.arange(-2, 2)
y = f(x)

Finally, you need to pass x and y as separate arguments to plot, not put them in a list:

plt.plot(x, y)

Upvotes: 0

efirvida
efirvida

Reputation: 4855

As @xnx answer my question few days ago "NumPy arrays have a fixed datatype (dtype) which is inferred from the initialization data if you don't specify it yourself. It won't change unless you tell it to"

And this is what happening here, you are using a range of int np.arange(-2, 2), and then the number has no floating point division.

import numpy as np
import math
import matplotlib.pyplot as plt

x = np.arange(-2., 2.)  #<-- use dots to define a float array
y = []

for i in range(-3, 3):
    y.append(math.exp(( x[i]**2/2 ) - x[i])-1)

y = np.array(y)
print x, y

# x = array([-2., -1.,  0.,  1.])    
# y = array([ 3.48168907, 0. , 0.39346934,  53.59815003, 3.48168907, 0.])

Upvotes: 0

Related Questions