PHP предоставляет обширный набор встроенных математических функций для работы с числами: от базового округления до тригонометрии, генерации случайных чисел и конвертации между системами счисления. Все эти функции доступны без подключения дополнительных расширений.
Базовые математические функции
abs() -- модуль числа
<?php
declare(strict_types=1);
// abs() returns the absolute value
echo abs(-42); // 42
echo abs(42); // 42
echo abs(-3.14); // 3.14
echo abs(0); // 0
// Practical: calculating distance between two points on a line
function distanceOnLine(float $a, float $b): float
{
return abs($a - $b);
}
echo distanceOnLine(10.5, 3.2); // 7.3
echo distanceOnLine(3.2, 10.5); // 7.3
ceil(), floor(), round() -- округление
<?php
declare(strict_types=1);
// ceil() — always rounds UP (ceiling)
echo ceil(4.1); // 5
echo ceil(4.9); // 5
echo ceil(-4.1); // -4
echo ceil(-4.9); // -4
echo ceil(5.0); // 5
// floor() — always rounds DOWN (floor)
echo floor(4.1); // 4
echo floor(4.9); // 4
echo floor(-4.1); // -5
echo floor(-4.9); // -5
echo floor(5.0); // 5
// round() — rounds to the nearest value
echo round(4.4); // 4
echo round(4.5); // 5
echo round(4.6); // 5
echo round(-4.5); // -5
// round() with precision (number of decimal places)
echo round(3.14159, 2); // 3.14
echo round(3.14159, 3); // 3.142
echo round(3.14159, 0); // 3.0
echo round(1234.5, -1); // 1230.0 (negative precision!)
echo round(1234.5, -2); // 1200.0
echo round(1250.0, -2); // 1300.0
Режимы округления round()
<?php
declare(strict_types=1);
// PHP_ROUND_HALF_UP — rounds 0.5 away from zero (default)
echo round(2.5, 0, PHP_ROUND_HALF_UP); // 3
echo round(-2.5, 0, PHP_ROUND_HALF_UP); // -3
echo round(3.55, 1, PHP_ROUND_HALF_UP); // 3.6
// PHP_ROUND_HALF_DOWN — rounds 0.5 toward zero
echo round(2.5, 0, PHP_ROUND_HALF_DOWN); // 2
echo round(-2.5, 0, PHP_ROUND_HALF_DOWN); // -2
echo round(3.55, 1, PHP_ROUND_HALF_DOWN); // 3.5
// PHP_ROUND_HALF_EVEN — rounds 0.5 to nearest even (banker's rounding)
echo round(2.5, 0, PHP_ROUND_HALF_EVEN); // 2 (2 is even)
echo round(3.5, 0, PHP_ROUND_HALF_EVEN); // 4 (4 is even)
echo round(4.5, 0, PHP_ROUND_HALF_EVEN); // 4 (4 is even)
echo round(5.5, 0, PHP_ROUND_HALF_EVEN); // 6 (6 is even)
// PHP_ROUND_HALF_ODD — rounds 0.5 to nearest odd
echo round(2.5, 0, PHP_ROUND_HALF_ODD); // 3 (3 is odd)
echo round(3.5, 0, PHP_ROUND_HALF_ODD); // 3 (3 is odd)
echo round(4.5, 0, PHP_ROUND_HALF_ODD); // 5 (5 is odd)
Banker's rounding (HALF_EVEN) -- используется в финансовых расчётах для минимизации систематической ошибки округления. При обычном округлении 0.5 всегда вверх -- за большое число операций сумма систематически завышается.
fmod(), intdiv(), fdiv() -- деление
<?php
declare(strict_types=1);
// fmod() — floating-point modulo (remainder)
echo fmod(10.5, 3.2); // 0.9 (10.5 - 3 * 3.2 = 0.9)
echo fmod(10, 3); // 1.0
echo fmod(-10, 3); // -1.0
// Difference from % operator: fmod works with floats
echo 10 % 3; // 1 (integer modulo)
// echo 10.5 % 3.2; // TypeError in PHP 8.0+ (int operands required)
echo fmod(10.5, 3.2); // 0.9 (float modulo works)
// intdiv() — integer division (truncated toward zero)
echo intdiv(7, 2); // 3
echo intdiv(-7, 2); // -3
echo intdiv(7, -2); // -3
echo intdiv(1, 3); // 0
// intdiv throws DivisionByZeroError
try {
intdiv(10, 0);
} catch (\DivisionByZeroError $e) {
echo $e->getMessage(); // "Division by zero"
}
// fdiv() — float division (PHP 8.0+)
// Unlike /, fdiv() returns INF or NAN instead of errors
echo fdiv(10, 3); // 3.3333333333333
echo fdiv(10, 0); // INF (no warning!)
echo fdiv(-10, 0); // -INF
echo fdiv(0, 0); // NAN
echo 10 / 0; // DivisionByZeroError in PHP 8.0+
Степени и логарифмы
<?php
declare(strict_types=1);
// pow() — exponentiation
echo pow(2, 8); // 256
echo pow(2, -1); // 0.5
echo pow(27, 1/3); // 3.0 (cube root)
echo 2 ** 8; // 256 (** operator, same as pow)
// sqrt() — square root
echo sqrt(144); // 12.0
echo sqrt(2); // 1.4142135623731
// sqrt of negative returns NAN
echo sqrt(-1); // NAN
var_dump(is_nan(sqrt(-1))); // true
// log() — natural logarithm (base e)
echo log(M_E); // 1.0
echo log(1); // 0.0
echo log(100); // 4.6051701859881
// log() with custom base (second argument)
echo log(8, 2); // 3.0 (log base 2 of 8)
echo log(1000, 10); // 3.0 (log base 10 of 1000)
// log2() — base-2 logarithm
echo log2(256); // 8.0
echo log2(1024); // 10.0
// log10() — base-10 logarithm (common logarithm)
echo log10(100); // 2.0
echo log10(1000); // 3.0
// exp() — e raised to the power
echo exp(0); // 1.0
echo exp(1); // 2.718281828... (M_E)
echo exp(2); // 7.3890560989307
// Practical: compound interest
function compoundInterest(
float $principal,
float $rate,
int $timesPerYear,
int $years
): float {
return $principal * pow(1 + $rate / $timesPerYear, $timesPerYear * $years);
}
// $10,000 at 5% annual, compounded monthly, for 10 years
echo compoundInterest(10000, 0.05, 12, 10); // 16470.09...
Тригонометрические функции
<?php
declare(strict_types=1);
// All trig functions work with RADIANS, not degrees!
// sin(), cos(), tan() — basic trigonometric functions
echo sin(0); // 0.0
echo sin(M_PI / 2); // 1.0
echo sin(M_PI); // ~0 (1.2246...e-16, floating point imprecision)
echo cos(0); // 1.0
echo cos(M_PI); // -1.0
echo tan(0); // 0.0
echo tan(M_PI / 4); // ~1.0
// Inverse trig functions: asin(), acos(), atan()
echo asin(1); // 1.5707963... (PI/2)
echo acos(0); // 1.5707963... (PI/2)
echo atan(1); // 0.7853981... (PI/4)
// atan2(y, x) — angle from X axis to point (x, y)
// Handles all quadrants correctly, unlike atan(y/x)
echo atan2(1, 1); // 0.7853981... (PI/4, 45 degrees)
echo atan2(1, -1); // 2.3561944... (3*PI/4, 135 degrees)
echo atan2(-1, -1); // -2.3561944... (-3*PI/4, -135 degrees)
echo atan2(0, -1); // 3.1415926... (PI, 180 degrees)
// deg2rad() and rad2deg() — conversion
echo deg2rad(180); // 3.1415926... (PI)
echo deg2rad(90); // 1.5707963... (PI/2)
echo deg2rad(360); // 6.2831853... (2*PI)
echo rad2deg(M_PI); // 180.0
echo rad2deg(1); // 57.29577951...
// Practical: distance between two GPS coordinates (Haversine formula)
function haversineDistance(
float $lat1, float $lon1,
float $lat2, float $lon2
): float {
$earthRadius = 6371; // km
$dLat = deg2rad($lat2 - $lat1);
$dLon = deg2rad($lon2 - $lon1);
$a = sin($dLat / 2) ** 2
+ cos(deg2rad($lat1)) * cos(deg2rad($lat2))
* sin($dLon / 2) ** 2;
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return $earthRadius * $c;
}
// Moscow to Saint Petersburg (~634 km)
echo haversineDistance(55.7558, 37.6173, 59.9343, 30.3351); // ~634.4
min(), max(), array_sum(), array_product()
<?php
declare(strict_types=1);
// min() and max() — with individual arguments
echo min(2, 3, 1, 6, 7); // 1
echo max(2, 3, 1, 6, 7); // 7
// min() and max() — with arrays
$numbers = [15, 3, 42, 8, 23];
echo min($numbers); // 3
echo max($numbers); // 42
// Be careful with mixed types!
echo min(0, 'hello'); // 0 (numeric comparison)
echo min('a', 'b'); // 'a' (string comparison)
// array_sum() — sum of all values
echo array_sum([1, 2, 3, 4, 5]); // 15
echo array_sum([1.5, 2.5, 3.0]); // 7.0
echo array_sum([]); // 0
// array_product() — product of all values
echo array_product([1, 2, 3, 4, 5]); // 120
echo array_product([2, 2, 2]); // 8
echo array_product([]); // 1 (empty product = 1)
// Practical: average, median, standard deviation
function average(array $numbers): float
{
if (count($numbers) === 0) {
throw new \InvalidArgumentException('Array cannot be empty');
}
return array_sum($numbers) / count($numbers);
}
function median(array $numbers): float
{
if (count($numbers) === 0) {
throw new \InvalidArgumentException('Array cannot be empty');
}
sort($numbers);
$count = count($numbers);
$middle = intdiv($count, 2);
if ($count % 2 === 0) {
return ($numbers[$middle - 1] + $numbers[$middle]) / 2;
}
return (float) $numbers[$middle];
}
function standardDeviation(array $numbers): float
{
$avg = average($numbers);
$squaredDiffs = array_map(
fn(float|int $n): float => ($n - $avg) ** 2,
$numbers
);
return sqrt(average($squaredDiffs));
}
$data = [4, 8, 15, 16, 23, 42];
echo average($data); // 18.0
echo median($data); // 15.5
echo standardDeviation($data); // 12.159...
Случайные числа
random_int() -- криптографически безопасный CSPRNG
<?php
declare(strict_types=1);
// random_int() — cryptographically secure random integer (PHP 7+)
// Uses /dev/urandom or CryptGenRandom — suitable for security
echo random_int(1, 100); // random number from 1 to 100
echo random_int(0, 1); // random 0 or 1 (coin flip)
echo random_int(PHP_INT_MIN, PHP_INT_MAX); // full range
// random_bytes() — cryptographically secure random bytes
$bytes = random_bytes(16); // 16 random bytes
echo bin2hex($bytes); // hex representation
// Generate random token
function generateToken(int $length = 32): string
{
return bin2hex(random_bytes($length));
}
echo generateToken(); // 64 hex characters
echo generateToken(16); // 32 hex characters
mt_rand() -- устаревший генератор (legacy)
<?php
declare(strict_types=1);
// mt_rand() — Mersenne Twister (NOT cryptographically secure!)
// Use ONLY for non-security purposes
echo mt_rand(); // random int
echo mt_rand(1, 100); // random int from 1 to 100
echo mt_getrandmax(); // maximum possible value (2147483647)
// rand() — alias for mt_rand() since PHP 7.1
echo rand(1, 100);
// NEVER use mt_rand/rand for:
// - Passwords, tokens, session IDs
// - Cryptographic keys
// - CSRF tokens
// - Any security-sensitive context
Random\Randomizer -- ООП API (PHP 8.2+)
<?php
declare(strict_types=1);
use Random\Randomizer;
use Random\Engine\Mt19937;
use Random\Engine\PcgOneseq128XslRr64;
use Random\Engine\Xoshiro256StarStar;
use Random\Engine\Secure;
// Default engine (Secure — CSPRNG)
$randomizer = new Randomizer();
echo $randomizer->nextInt(); // random int
echo $randomizer->getInt(1, 100); // random int in range
echo $randomizer->getBytes(16); // 16 random bytes
// Shuffle array
$cards = range(1, 52);
$shuffled = $randomizer->shuffleArray($cards);
// Shuffle string
echo $randomizer->shuffleBytes('Hello World'); // random permutation
// Pick random keys from array
$items = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
$picked = $randomizer->pickArrayKeys($items, 3); // 3 random keys
// Get random float in [0, 1) — PHP 8.3+
// echo $randomizer->nextFloat(); // 0.0 <= x < 1.0
// echo $randomizer->getFloat(0.0, 1.0); // float in range
// Mt19937 engine — deterministic, reproducible sequences
$seeded = new Randomizer(new Mt19937(42));
echo $seeded->getInt(1, 100); // always same sequence for seed 42
echo $seeded->getInt(1, 100); // always same second value
// PcgOneseq128XslRr64 — fast, good statistical properties
$pcg = new Randomizer(new PcgOneseq128XslRr64(12345));
echo $pcg->getInt(1, 1000);
// Xoshiro256StarStar — extremely fast, good for simulations
$xoshiro = new Randomizer(new Xoshiro256StarStar(98765));
echo $xoshiro->getInt(1, 1000);
// Secure engine — explicit CSPRNG (same as default)
$secure = new Randomizer(new Secure());
echo $secure->getInt(1, 1000);
// Practical: weighted random selection
function weightedRandom(Randomizer $rng, array $weights): string
{
$total = array_sum($weights);
$roll = $rng->getInt(1, $total);
$cumulative = 0;
foreach ($weights as $item => $weight) {
$cumulative += $weight;
if ($roll <= $cumulative) {
return (string) $item;
}
}
throw new \LogicException('Unreachable');
}
$loot = [
'common' => 60,
'uncommon' => 25,
'rare' => 10,
'legendary' => 5,
];
echo weightedRandom(new Randomizer(), $loot); // random loot drop
Конвертация между системами счисления
<?php
declare(strict_types=1);
// base_convert() — convert between any bases (2 to 36)
echo base_convert('ff', 16, 10); // "255" (hex to decimal)
echo base_convert('255', 10, 16); // "ff" (decimal to hex)
echo base_convert('255', 10, 2); // "11111111" (decimal to binary)
echo base_convert('377', 8, 10); // "255" (octal to decimal)
// Specialized functions (faster, type-aware)
// Binary
echo decbin(255); // "11111111"
echo bindec('11111111'); // 255
// Octal
echo decoct(255); // "377"
echo octdec('377'); // 255
// Hexadecimal
echo dechex(255); // "ff"
echo hexdec('ff'); // 255
echo dechex(16777215); // "ffffff" (white color in RGB)
// Practical: color conversion
function hexToRgb(string $hex): array
{
$hex = ltrim($hex, '#');
// Support shorthand (#fff -> #ffffff)
if (strlen($hex) === 3) {
$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
}
return [
'r' => hexdec(substr($hex, 0, 2)),
'g' => hexdec(substr($hex, 2, 2)),
'b' => hexdec(substr($hex, 4, 2)),
];
}
function rgbToHex(int $r, int $g, int $b): string
{
return sprintf('#%02x%02x%02x', $r, $g, $b);
}
var_dump(hexToRgb('#ff6600')); // ['r' => 255, 'g' => 102, 'b' => 0]
echo rgbToHex(255, 102, 0); // "#ff6600"
Математические константы
<?php
declare(strict_types=1);
// Mathematical constants
echo M_PI; // 3.1415926535898 — Pi
echo M_E; // 2.718281828459 — Euler's number (e)
echo M_LOG2E; // 1.442695040889 — log2(e)
echo M_LOG10E; // 0.43429448190325 — log10(e)
echo M_LN2; // 0.69314718055995 — ln(2)
echo M_LN10; // 2.302585092994 — ln(10)
echo M_PI_2; // 1.5707963267949 — Pi/2
echo M_PI_4; // 0.78539816339745 — Pi/4
echo M_1_PI; // 0.31830988618379 — 1/Pi
echo M_2_PI; // 0.63661977236758 — 2/Pi
echo M_SQRT2; // 1.4142135623731 — sqrt(2)
echo M_SQRT3; // 1.7320508075689 — sqrt(3)
echo M_SQRT1_2; // 0.70710678118655 — 1/sqrt(2)
// PHP integer/float limits
echo PHP_INT_MAX; // 9223372036854775807 (on 64-bit)
echo PHP_INT_MIN; // -9223372036854775808
echo PHP_INT_SIZE; // 8 (bytes on 64-bit)
echo PHP_FLOAT_MAX; // 1.7976931348623E+308
echo PHP_FLOAT_MIN; // 2.2250738585072E-308 (smallest positive normalized)
echo PHP_FLOAT_EPSILON; // 2.2204460492503E-16 (smallest x such that 1.0 + x != 1.0)
echo PHP_FLOAT_DIG; // 15 (number of significant digits)
// Special float values
echo INF; // INF (infinity)
echo -INF; // -INF
echo NAN; // NAN (Not a Number)
echo log(0); // -INF
echo acos(2); // NAN (argument out of range)
is_nan(), is_infinite(), is_finite()
<?php
declare(strict_types=1);
// is_nan() — check if value is Not A Number
var_dump(is_nan(NAN)); // true
var_dump(is_nan(sqrt(-1))); // true
var_dump(is_nan(acos(2))); // true
var_dump(is_nan(42)); // false
var_dump(is_nan(INF)); // false (infinity is not NAN)
// IMPORTANT: NAN !== NAN (NAN is never equal to anything, even itself)
var_dump(NAN == NAN); // false!
var_dump(NAN === NAN); // false!
// Always use is_nan() for checks
// is_infinite() — check for +/- infinity
var_dump(is_infinite(INF)); // true
var_dump(is_infinite(-INF)); // true
var_dump(is_infinite(log(0))); // true (-INF)
var_dump(is_infinite(42)); // false
var_dump(is_infinite(NAN)); // false
// is_finite() — check if value is a finite number
var_dump(is_finite(42)); // true
var_dump(is_finite(3.14)); // true
var_dump(is_finite(INF)); // false
var_dump(is_finite(NAN)); // false
// Practical: safe division function
function safeDivide(float $a, float $b): float|null
{
$result = fdiv($a, $b);
if (!is_finite($result)) {
return null;
}
return $result;
}
echo safeDivide(10, 3) ?? 'undefined'; // 3.3333...
echo safeDivide(10, 0) ?? 'undefined'; // "undefined"
echo safeDivide(0, 0) ?? 'undefined'; // "undefined" (NAN)
Практические примеры
Расчёт вероятности
<?php
declare(strict_types=1);
// Factorial using array_product
function factorial(int $n): int
{
if ($n < 0) {
throw new \InvalidArgumentException('Factorial of negative number');
}
if ($n <= 1) {
return 1;
}
return array_product(range(1, $n));
}
// Combinations C(n, k) = n! / (k! * (n-k)!)
function combinations(int $n, int $k): int
{
if ($k > $n || $k < 0) {
return 0;
}
return intdiv(factorial($n), factorial($k) * factorial($n - $k));
}
// Permutations P(n, k) = n! / (n-k)!
function permutations(int $n, int $k): int
{
return intdiv(factorial($n), factorial($n - $k));
}
echo factorial(10); // 3628800
echo combinations(52, 5); // 2598960 (poker hands)
echo permutations(10, 3); // 720
// Probability of getting at least one six in 4 dice throws
$probNoSix = pow(5/6, 4);
$probAtLeastOne = 1 - $probNoSix;
echo round($probAtLeastOne * 100, 2) . '%'; // 51.77%
Геометрические вычисления
<?php
declare(strict_types=1);
// Circle area and perimeter
function circleArea(float $radius): float
{
return M_PI * $radius ** 2;
}
function circlePerimeter(float $radius): float
{
return 2 * M_PI * $radius;
}
// Euclidean distance between 2D points
function distance2D(float $x1, float $y1, float $x2, float $y2): float
{
return sqrt(($x2 - $x1) ** 2 + ($y2 - $y1) ** 2);
}
// Angle between two 2D vectors
function angleBetween(
float $x1, float $y1,
float $x2, float $y2
): float {
$dot = $x1 * $x2 + $y1 * $y2;
$mag1 = sqrt($x1 ** 2 + $y1 ** 2);
$mag2 = sqrt($x2 ** 2 + $y2 ** 2);
return rad2deg(acos($dot / ($mag1 * $mag2)));
}
echo circleArea(5); // 78.539...
echo circlePerimeter(5); // 31.415...
echo distance2D(0, 0, 3, 4); // 5.0
echo angleBetween(1, 0, 0, 1); // 90.0