Power Exp Log
NumPy provides element-wise power, exponential, and logarithmic functions.
Power Operations
1. Using ** Operator
import numpy as np
def main():
a = np.array([[1, 2], [3, 4]])
print("a =")
print(a)
print()
print("a ** 2 =")
print(a ** 2)
if __name__ == "__main__":
main()
2. Using np.power
import numpy as np
def main():
a = np.array([[1, 2], [3, 4]])
# Equivalent to a ** 2
b = np.power(a, 2)
print("np.power(a, 2) =")
print(b)
if __name__ == "__main__":
main()
3. Base as Array
import numpy as np
def main():
a = np.array([[1, 2], [3, 4]])
# 2 raised to each element
b = 2 ** a
c = np.power(2, a)
print("2 ** a =")
print(b)
print()
print("np.power(2, a) =")
print(c)
if __name__ == "__main__":
main()
Square Root
1. np.sqrt
import numpy as np
def main():
a = np.array([1, 4, 9, 16, 25])
print(f"a = {a}")
print(f"np.sqrt(a) = {np.sqrt(a)}")
print(f"a ** 0.5 = {a ** 0.5}")
if __name__ == "__main__":
main()
2. Cube Root
import numpy as np
def main():
a = np.array([1, 8, 27, 64])
print(f"a = {a}")
print(f"np.cbrt(a) = {np.cbrt(a)}")
print(f"a ** (1/3) = {a ** (1/3)}")
if __name__ == "__main__":
main()
3. Negative Values
import numpy as np
def main():
a = np.array([-1, -4, -9])
# sqrt of negative returns nan
print(f"np.sqrt({a}) = {np.sqrt(a)}")
# Use complex dtype
a_complex = a.astype(complex)
print(f"np.sqrt({a_complex}) = {np.sqrt(a_complex)}")
if __name__ == "__main__":
main()
Exponential
1. np.exp
import numpy as np
def main():
x = np.array([0, 1, 2, 3])
print(f"x = {x}")
print(f"np.exp(x) = {np.exp(x)}")
print(f"e^0 = {np.exp(0):.4f}")
print(f"e^1 = {np.exp(1):.4f}")
if __name__ == "__main__":
main()
2. np.exp2
import numpy as np
def main():
x = np.array([0, 1, 2, 3, 4])
print(f"x = {x}")
print(f"np.exp2(x) = {np.exp2(x)}") # 2^x
print(f"2 ** x = {2 ** x}")
if __name__ == "__main__":
main()
3. np.expm1
import numpy as np
def main():
# exp(x) - 1, more accurate for small x
x = np.array([1e-10, 1e-5, 0.1, 1.0])
print("x exp(x)-1 expm1(x)")
for val in x:
print(f"{val:.0e} {np.exp(val)-1:.10f} {np.expm1(val):.10f}")
if __name__ == "__main__":
main()
Logarithm
1. Natural Log (ln)
import numpy as np
def main():
x = np.array([1, np.e, np.e**2, np.e**3])
print(f"x = {x}")
print(f"np.log(x) = {np.log(x)}")
if __name__ == "__main__":
main()
2. Log Base 10
import numpy as np
def main():
x = np.array([1, 10, 100, 1000])
print(f"x = {x}")
print(f"np.log10(x) = {np.log10(x)}")
if __name__ == "__main__":
main()
3. Log Base 2
import numpy as np
def main():
x = np.array([1, 2, 4, 8, 16])
print(f"x = {x}")
print(f"np.log2(x) = {np.log2(x)}")
if __name__ == "__main__":
main()
np.log1p
1. Log of 1+x
import numpy as np
def main():
# log(1+x), more accurate for small x
x = np.array([1e-10, 1e-5, 0.1, 1.0])
print("x log(1+x) log1p(x)")
for val in x:
print(f"{val:.0e} {np.log(1+val):.10f} {np.log1p(val):.10f}")
if __name__ == "__main__":
main()
2. Why Use log1p
For very small x, log(1+x) loses precision due to floating point.
3. Inverse Relationship
import numpy as np
def main():
x = np.array([0.1, 0.5, 1.0])
# expm1 and log1p are inverses
print(f"x = {x}")
print(f"log1p(expm1(x)) = {np.log1p(np.expm1(x))}")
print(f"expm1(log1p(x)) = {np.expm1(np.log1p(x))}")
if __name__ == "__main__":
main()
Visualization
1. Exp and Log Curves
import numpy as np
import matplotlib.pyplot as plt
def main():
x_log = np.linspace(0.1, 10, 100)
y_log = np.log(x_log)
x_exp = np.linspace(-2, 2, 100)
y_exp = np.exp(x_exp)
fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(12, 4))
ax0.plot(x_log, y_log, 'r-', linewidth=2)
ax0.axhline(0, linestyle='--', alpha=0.3, color='blue')
ax0.axvline(0, linestyle='--', alpha=0.3, color='blue')
ax0.set_title('y = ln(x)')
ax0.set_xlabel('x')
ax0.set_ylabel('y')
ax0.grid(True, alpha=0.3)
ax1.plot(x_exp, y_exp, 'r-', linewidth=2)
ax1.axhline(0, linestyle='--', alpha=0.3, color='blue')
ax1.axvline(0, linestyle='--', alpha=0.3, color='blue')
ax1.set_title('y = exp(x)')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
if __name__ == "__main__":
main()
2. Power Functions
import numpy as np
import matplotlib.pyplot as plt
def main():
x = np.linspace(0, 3, 100)
fig, ax = plt.subplots(figsize=(8, 5))
for n in [0.5, 1, 2, 3]:
ax.plot(x, x ** n, label=f'x^{n}')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Power Functions')
ax.legend()
ax.grid(True, alpha=0.3)
ax.set_ylim(0, 10)
plt.show()
if __name__ == "__main__":
main()
Applications
1. Compound Interest
import numpy as np
def main():
principal = 1000
rate = 0.05
years = np.arange(1, 11)
# A = P * e^(rt) for continuous compounding
amount = principal * np.exp(rate * years)
print("Continuous Compounding at 5%")
print("Year | Amount")
print("-" * 20)
for y, a in zip(years, amount):
print(f" {y:2} | ${a:.2f}")
if __name__ == "__main__":
main()
2. Decibels
import numpy as np
def main():
# Power ratios
ratios = np.array([0.1, 0.5, 1, 2, 10, 100])
# Convert to decibels
db = 10 * np.log10(ratios)
print("Ratio | dB")
print("-" * 20)
for r, d in zip(ratios, db):
print(f"{r:5.1f} | {d:+.1f} dB")
if __name__ == "__main__":
main()
3. Softmax Function
import numpy as np
def softmax(x):
# Subtract max for numerical stability
exp_x = np.exp(x - np.max(x))
return exp_x / np.sum(exp_x)
def main():
logits = np.array([2.0, 1.0, 0.1])
probs = softmax(logits)
print(f"Logits: {logits}")
print(f"Softmax: {probs}")
print(f"Sum: {probs.sum():.4f}")
if __name__ == "__main__":
main()
Summary Table
1. Power Functions
| Function |
Description |
a ** b |
Power operator |
np.power(a, b) |
Element-wise power |
np.sqrt(a) |
Square root |
np.cbrt(a) |
Cube root |
np.square(a) |
Square (a²) |
2. Exponential Functions
| Function |
Description |
np.exp(x) |
e^x |
np.exp2(x) |
2^x |
np.expm1(x) |
e^x - 1 (accurate for small x) |
3. Logarithm Functions
| Function |
Description |
np.log(x) |
Natural log (ln) |
np.log10(x) |
Log base 10 |
np.log2(x) |
Log base 2 |
np.log1p(x) |
ln(1+x) (accurate for small x) |