Mathematics7 min readExamples run on PHP 8.5.10

tanh()

Learn how PHP 8.4 tanh() computes the hyperbolic tangent of a float, with practical examples, saturation and NAN edge cases, and common mistakes to avoid.

Signature

tanh(float $num): float
Available since PHP 4.1.07.48.08.18.28.38.48.5All versions →

Purpose

tanh() returns the hyperbolic tangent of a number. It is defined as sinh($num) / cosh($num). Unlike the ordinary trigonometric tan(), it is not about angles on a circle. It is a smooth S-shaped curve that maps any real number into the range from -1 to 1. That makes it useful for squashing values into a bounded range, for example as an activation function in small neural-network calculations, for normalising scores, or for soft clipping in numeric code.

Signature

Parameters and defaults

  • $num: the value to process. It is required and has no default. Any finite float or integer is accepted, and integers are converted to float.

In the default (non-strict) typing mode, numeric strings such as "0.5" are coerced to float. With declare(strict_types=1) only int and float values are accepted. A non-numeric string such as "abc" throws a TypeError.

Return value and failure cases

The function always returns a float. The result lies between -1 and 1 inclusive:

  • tanh(0) is 0.0, and the function is odd, so tanh(-$x) equals -tanh($x).
  • For large positive arguments the result reaches exactly 1.0, and for large negative arguments it reaches -1.0, because the true value is closer to the limit than a double can represent.
  • tanh(INF) is 1.0 and tanh(-INF) is -1.0.
  • tanh(NAN) is NAN.

There is no false return and no warning for out-of-range input. The only failure is a TypeError when the argument cannot be used as a number.

Example 1: sampling the curve

The curve rises steeply near zero and flattens as the input grows. Rounding keeps the output stable and readable.

Example
<?php
$inputs = [0.5, 1, 2];
$results = array_map(fn(float $x): float => round(tanh($x), 4), $inputs);
echo json_encode($results), "\n";
Output
[0.4621,0.7616,0.964]

Notice how the step from 1 to 2 adds far less than the step from 0.5 to 1. This flattening is called saturation.

Example 2: saturation and special values

For large magnitudes the result is exactly 1 or -1, and special floats behave predictably.

Example
<?php
var_dump(tanh(30));
var_dump(tanh(-30));
var_dump(tanh(INF));
var_dump(is_nan(tanh(NAN)));
Output
float(1)
float(-1)
float(1)
bool(true)

Compare results with is_nan() rather than === or ==, because NAN is never equal to anything, including itself.

Example 3: a tiny neuron

A weighted sum passed through tanh() gives an output in the range -1 to 1. This is a classic use of the function.

Example
<?php
function neuron(array $inputs, array $weights): float
{
    $sum = 0.0;
    foreach ($inputs as $i => $value) {
        $sum += $value * $weights[$i];
    }
    return tanh($sum);
}

echo json_encode(round(neuron([0.5, -1.0, 2.0], [0.8, 0.3, 0.4]), 4)), "\n";
Output
0.7163

The weighted sum here is about 0.9, and tanh(0.9) is roughly 0.7163. The result is rounded to hide tiny floating-point noise.

Edge cases

  • Saturation: beyond roughly magnitude 20 the output is indistinguishable from 1 or -1. Different inputs then produce identical results, so the function cannot be inverted there. atanh() of exactly 1 gives infinity.
  • Precision near zero: for very small $num, tanh($num) is almost equal to $num itself.
  • Float comparison: results are approximations. Compare with a tolerance, such as abs($a - $b) < 1e-12, instead of strict equality, unless you are testing against the exact limits.
  • Integers: passing 0 or 1 is fine, but the return is still a float, so var_dump(tanh(0)) shows float(0).

Common mistakes

  1. Confusing it with tan(). tan() is periodic and unbounded, while tanh() is bounded and never repeats.
  2. Passing degrees. Hyperbolic functions do not use angles, so there is nothing to convert with deg2rad().
  3. Printing unrounded floats in tests. Expected outputs with long decimal tails are fragile. Round, or compare with a tolerance.
  4. Expecting a different range. If you need 0 to 1 rather than -1 to 1, rescale with (tanh($x) + 1) / 2.
  5. Feeding it text. Validate user input first, because a non-numeric string raises a TypeError.
  • tan(): the ordinary tangent of an angle in radians.
  • atanh(): the inverse hyperbolic tangent, which reverses tanh() for results strictly between -1 and 1.
  • sinh(): hyperbolic sine, the numerator in the definition.
  • cosh(): hyperbolic cosine, the denominator in the definition.

Recap

tanh(float $num): float computes sinh($num) / cosh($num) and always returns a float from -1 to 1. It is odd, smooth and saturating, returns NAN for NAN, and reaches exactly 1 or -1 for large inputs. Round or use a tolerance when comparing results, and do not confuse it with tan().

Tested examples

Sampling the tanh curve
<?php
$inputs = [0.5, 1, 2];
$results = array_map(fn(float $x): float => round(tanh($x), 4), $inputs);
echo json_encode($results), "\n";
Output
[0.4621,0.7616,0.964]
Saturation and special values
<?php
var_dump(tanh(30));
var_dump(tanh(-30));
var_dump(tanh(INF));
var_dump(is_nan(tanh(NAN)));
Output
float(1)
float(-1)
float(1)
bool(true)
A tiny neuron using tanh as activation
<?php
function neuron(array $inputs, array $weights): float
{
    $sum = 0.0;
    foreach ($inputs as $i => $value) {
        $sum += $value * $weights[$i];
    }
    return tanh($sum);
}

echo json_encode(round(neuron([0.5, -1.0, 2.0], [0.8, 0.3, 0.4]), 4)), "\n";
Output
0.7163