The math.tanh(x) function computes the hyperbolic tangent of a real numeric value x. Defined as the ratio of hyperbolic sine to hyperbolic cosine, tanh(x) = sinh(x) / cosh(x) = (ex − e−x) / (ex + e−x), it accepts any real number across (−∞, +∞) and compresses it into a smooth, strictly bounded S-shaped range between −1.0 and +1.0.
Exact Inverse: Reverses the inverse hyperbolic tangent math.atanh() (math.tanh(math.atanh(y)) == y for any y ∈ (−1.0, 1.0)). Widely utilized as a zero-centered activation function in machine learning neural networks.
The math.tanh() function is part of Python's standard math module:
import math
result = math.tanh(x)
| Parameter | Type | Description |
|---|---|---|
x |
float or int |
Required. A real number representing the hyperbolic parameter. |
| Return Value | float |
The hyperbolic tangent of x, strictly bounded in the open interval (−1.0, 1.0). |
TypeError |
Exception | Raised when passing non-numeric types (e.g. strings or lists). |
Because tanh(x) is an odd function, it has point symmetry through the origin: tanh(-x) == -tanh(x), with tanh(0.0) == 0.0:
import math
# Origin value
print("tanh(0.0): ", math.tanh(0.0)) # Output: 0.0
# Odd Symmetry: tanh(-x) == -tanh(x)
print("tanh(1.0): ", round(math.tanh(1.0), 6)) # Output: 0.761594
print("tanh(-1.0):", round(math.tanh(-1.0), 6)) # Output: -0.761594
print("tanh(2.0): ", round(math.tanh(2.0), 6)) # Output: 0.964028
print("tanh(-2.0):", round(math.tanh(-2.0), 6)) # Output: -0.964028
Output:
tanh(0.0): 0.0
tanh(1.0): 0.761594
tanh(-1.0): -0.761594
tanh(2.0): 0.964028
tanh(-2.0): -0.964028
Verifying the quotient relationship math.sinh(x) / math.cosh(x):
val = 2.5
from_tanh = math.tanh(val)
from_ratio = math.sinh(val) / math.cosh(val)
print("math.tanh(2.5): ", from_tanh)
print("sinh(2.5)/cosh(2.5):", from_ratio)
print("Matches? ", math.isclose(from_tanh, from_ratio))
Output:
math.tanh(2.5): 0.9866142981514303
sinh(2.5)/cosh(2.5): 0.9866142981514303
Matches? True
Unlike math.sinh() and math.cosh() which explode exponentially for large numbers (triggering OverflowError), math.tanh(x) never overflows. As |x| increases, the value smoothly approaches +1.0 or −1.0:
import math
print("tanh(5): ", math.tanh(5)) # 0.9999092042625951
print("tanh(20): ", math.tanh(20)) # 1.0 (exact in float precision)
print("tanh(1000):", math.tanh(1000)) # 1.0 (no OverflowError!)
print("tanh(-1000):", math.tanh(-1000)) # -1.0
# Handling infinite limits
print("tanh(inf): ", math.tanh(float('inf'))) # 1.0
print("tanh(-inf):", math.tanh(float('-inf'))) # -1.0
Output:
tanh(5): 0.9999092042625951
tanh(20): 1.0
tanh(1000): 1.0
tanh(-1000): -1.0
tanh(inf): 1.0
tanh(-inf): -1.0
In deep learning, tanh is often preferred over the standard logistic sigmoid function σ(z) = 1 / (1 + e−z) for hidden layers:
tanh outputs values centered around 0.0 in (−1, 1), whereas sigmoid outputs strictly positive values in (0, 1). Zero-centered activations prevent systematic directional bias in gradient weight updates.tanh(z) = 2 · σ(2z) − 1.tanh'(z) = 1 − tanh²(z).import math
def tanh_activation_and_derivative(z):
activated = math.tanh(z)
derivative = 1.0 - activated**2
return (activated, derivative)
inputs = [-3.0, -1.0, 0.0, 1.0, 3.0]
print(f"{'Input z':>8} | {'tanh(z)':>10} | {'tanh\'(z)':>10}")
print("-" * 34)
for z in inputs:
act, der = tanh_activation_and_derivative(z)
print(f"{z:8.1f} | {act:10.4f} | {der:10.4f}")
Output:
Input z | tanh(z) | tanh'(z)
----------------------------------
-3.0 | -0.9951 | 0.0099
-1.0 | -0.7616 | 0.4200
0.0 | 0.0000 | 1.0000
1.0 | 0.7616 | 0.4200
3.0 | 0.9951 | 0.0099
tanh'(z) drops to 0.0099 at |z| = 3.0. In very deep neural networks, this causes the vanishing gradient problem, which motivated modern alternatives like ReLU.
Circular math.tan() and hyperbolic math.tanh() share naming conventions but have fundamentally distinct graphs and mathematical functions:
| Property | Circular math.tan(x) |
Hyperbolic math.tanh(x) |
|---|---|---|
| Domain | Discontinuous (vertical asymptotes at ±π/2, ±3π/2) | Continuous across (−∞, +∞) |
| Range | Unbounded: (−∞, +∞) |
Strictly bounded: (−1.0, 1.0) |
| Periodicity | Periodic: Repeats every π radians | Non-periodic: Monotonic S-curve |
| Input Units | Angle in radians | Dimensionless real parameter |
| Inverse Pair | math.atan() |
math.atanh() |
Visualizing the smooth sigmoidal curve bounded by asymptotes at y = ±1.0 using Matplotlib:
import math
import matplotlib.pyplot as plt
x_vals = [i * 0.1 - 5.0 for i in range(0, 101)] # -5.0 to +5.0
y_vals = [math.tanh(x) for x in x_vals]
plt.plot(x_vals, y_vals, label="y = tanh(x)", color="#1a73e8", linewidth=2)
plt.axhline(1.0, color="red", linestyle="--", alpha=0.7, label="Asymptote y = +1.0")
plt.axhline(-1.0, color="red", linestyle="--", alpha=0.7, label="Asymptote y = -1.0")
plt.axvline(0.0, color="gray", linewidth=0.8)
plt.title("Hyperbolic Tangent: S-Curve Activation")
plt.xlabel("x")
plt.ylabel("tanh(x)")
plt.grid(True, linestyle=":", alpha=0.6)
plt.legend()
plt.show()
In Einstein's Special Theory of Relativity, physical velocities cannot exceed the speed of light c. As a result, velocities do not add linearly (Galilean addition v1 + v2). Instead, velocities correspond to hyperbolic angles known as rapidities (w = atanh(v / c)), and rapidities add linearly:
Because tanh is bounded by (−1, 1), no matter how close v1 and v2 are to the speed of light, the combined velocity strictly never exceeds c. Let's build a relativistic velocity calculator:
import math
SPEED_OF_LIGHT = 299792458.0 # c in m/s
def relativistic_velocity_addition(v1, v2, c=SPEED_OF_LIGHT):
"""
Combines two velocities v1 and v2 relativistically:
v_total = c * tanh(atanh(v1/c) + atanh(v2/c))
"""
if abs(v1) >= c or abs(v2) >= c:
raise ValueError("Subluminal velocities must be strictly less than c.")
rapidity1 = math.atanh(v1 / c)
rapidity2 = math.atanh(v2 / c)
combined_v = c * math.tanh(rapidity1 + rapidity2)
return round(combined_v, 2)
# Unit Assertions
# 1. Combining 0 m/s with 100,000 m/s yields 100,000 m/s
assert relativistic_velocity_addition(0.0, 100000.0) == 100000.0
# 2. Combining 0.75 c and 0.75 c:
# Galilean sum would be 1.5 c (impossible!)
# Relativistic sum: (0.75 + 0.75) / (1 + 0.75*0.75) c = 1.5 / 1.5625 c = 0.96 c
v_sub = 0.75 * SPEED_OF_LIGHT
expected_c_fraction = round(0.96 * SPEED_OF_LIGHT, 2)
assert relativistic_velocity_addition(v_sub, v_sub) == expected_c_fraction
# 3. Opposite velocities cancel out
assert relativistic_velocity_addition(v_sub, -v_sub) == 0.0
# Validation error check for >= c
try:
relativistic_velocity_addition(SPEED_OF_LIGHT, 1000.0)
assert False, "Should raise ValueError"
except ValueError:
pass
print("Two 0.75c spaceships combined velocity:", relativistic_velocity_addition(v_sub, v_sub), "m/s")
print("All relativistic velocity assertions passed successfully!")
Open in Google Colab View on GitHub
Run all math.tanh() examples interactively, test asymptotic saturation at ±1.0, benchmark neural network derivatives, and simulate relativistic velocity addition in Google Colab.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.