0

I'm wondering when is it appropriate to use math.exp versus np.exp? In general, when can and should one use methods from the math module versus numpy during vectorization operations?

For example, the below snippet generates an error due to the use of math.exp:

z = np.random.standard_normal((11, 10000))
s = np.zeros_like(z)
s[0] = 10
dt = 1/10
v = 0.25
r=0

s[1] = s[0]*math.exp((r - v ** 2 / 2)*dt + v * math.sqrt(dt) * z[1])
s[1]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-250-ce2a501848b9> in <module>
----> 1 s[1] = s[0]*math.exp((r - v ** 2 / 2)*dt + v * math.sqrt(dt) * z[1])
      2 s[1]

TypeError: only size-1 arrays can be converted to Python scalars

When I replace, math.exp with np.exp, I obtain the desired results. However, I'm unsure why math.sqrt in the second part of the equation didn't generate a similar error?

s[1] = s[0]*np.exp((r - v ** 2 / 2)*dt + v * math.sqrt(dt) * z[1])
s[1]
array([  8.845,  11.254,  10.881, ...,   8.994,   8.672,   9.614])
jgg
  • 791
  • 4
  • 17
  • Is the question which one to use when both would give the same result? Or is it which uses each is best suited for? If the second, just looking at the signature should give you the answer. – norok2 Mar 31 '21 at 22:00
  • 2
    When working with single numbers like `dt` you can use `math` functions. When working with arrays like `r`, you must use the `numpy` ones. `numpy` will work for single numbers, but the `math` ones will be faster (but it may not worth the extra import). – hpaulj Mar 31 '21 at 23:13

2 Answers2

1

If working with numpy, prefer numpy.exp, because it supports numpy arrays. math.exp does not -- it only works on single values.

math.exp(dt) works because dt is a single floating point value (dt=1/10).

jkr
  • 17,119
  • 2
  • 42
  • 68
1

math.exp expects a single number. And Python will try to convert (r - v ** 2 / 2)*dt + v * math.sqrt(dt) * z[1] into a skalar, which is not possible because that thing is acctually a vector of rank 1. So it gives an error.

As for the second question: v * math.sqrt(dt) * z[1] evaluates to a vector. math.sqrt(dt) returns a skalar. Because numpy treats skalar-vector or skalar-matrix multiplication as elementwise multiplication, the code is legal.

My suggestion is stick with numpy if you've already imported the library in your project. Actually you can mix math and numpy facilities anyway you want if you know what happens behind the scene.

Check the following link for a quick demonstration for numpy. It takes about 30min. But it will equip you with enough basic knowledge and show you further references to advanced features of numpy. https://cs231n.github.io/python-numpy-tutorial/

Shihao Xu
  • 721
  • 1
  • 7
  • 14