Oihana PHP

maths

Table of Contents

Classes

Dimension
Defines the canonical keys of a two-dimensional size pair.

Functions

aspectFit()  : array{width: int, height: int}
Scales a dimension pair to a target width or height while preserving the original aspect ratio (the locked-ratio behaviour of an aspect-ratio box).
aspectRatio()  : string
Returns the aspect ratio of a width and a height, simplified by their greatest common divisor, e.g. `"16:9"` for 1920 × 1080.
bearing()  : float
Calculates the initial bearing (sometimes referred to as forward azimuth) which if followed in a straight line along a great-circle arc will take you from the start point to the end point (in degrees).
cartesianToPolar()  : array{angle: float, radius: float}
Converts a cartesian vector to polar coordinates.
ceilValue()  : float
Rounds a number up to a count of decimal places.
factorial()  : int
Computes the factorial `n!` of a non-negative integer.
fixAngle()  : float
Normalize an angle in degrees to the range [0, 360).
floorValue()  : float
Rounds a number down to a count of decimal places.
gcd()  : int
Calculate the Greatest Common Divisor (GCD) of two integers using the Euclidean algorithm.
haversine()  : float
Calculate the great-circle distance between two points on a sphere using the Haversine formula.
isPrime()  : bool
Tells whether an integer is a prime number.
mean()  : float
Computes the arithmetic mean (average) of a list of numbers.
median()  : float
Computes the median (middle value) of a list of numbers.
polarToCartesian()  : array{x: float, y: float}
Converts a polar coordinate to a cartesian vector.
roundValue()  : float
Rounds a number to a count of decimal places.
shedFloatNoise()  : float
Sheds the binary noise a computed figure carries, and rounds no business figure.
stddev()  : float
Computes the standard deviation of a list of numbers.
variance()  : float
Computes the variance of a list of numbers.

Functions

aspectFit()

Scales a dimension pair to a target width or height while preserving the original aspect ratio (the locked-ratio behaviour of an aspect-ratio box).

aspectFit(int $width, int $height[, int|null $targetWidth = null ][, int|null $targetHeight = null ]) : array{width: int, height: int}

Provide $targetWidth to derive the matching height, or $targetHeight to derive the matching width. If both are given, $targetWidth takes precedence and $targetHeight is ignored. If both are null, the original pair is returned. A non-positive original $width/$height yields an undefined ratio: the provided targets (or the originals) are returned unchanged.

Parameters
$width : int

The original (reference) width.

$height : int

The original (reference) height.

$targetWidth : int|null = null

The desired width, or null.

$targetHeight : int|null = null

The desired height, or null.

Tags
example
use function oihana\core\maths\aspectFit ;

aspectFit( 1920 , 1080 , targetWidth: 1280 ) ; // [ 'width' => 1280 , 'height' => 720 ]
aspectFit( 1920 , 1080 , targetHeight: 540 ) ; // [ 'width' => 960  , 'height' => 540 ]
author

Marc Alcaraz (ekameleon)

since
1.1.0
Return values
array{width: int, height: int} —

The scaled dimensions preserving the ratio.

aspectRatio()

Returns the aspect ratio of a width and a height, simplified by their greatest common divisor, e.g. `"16:9"` for 1920 × 1080.

aspectRatio(int $width, int $height[, string $separator = ':' ]) : string

The two numbers are divided by gcd(): 1920 × 1080 and 1280 × 720 both give "16:9", 1280 × 1080 gives "32:27". The separator defaults to a colon and can be changed ("16/9").

A width or a height of zero or below has no ratio — and a negative one would be read as its absolute value by gcd(), hiding an error upstream: both throw rather than return a string a screen would show without anyone knowing why.

To scale a size while keeping its ratio, see aspectFit().

Parameters
$width : int

The width, greater than 0.

$height : int

The height, greater than 0.

$separator : string = ':'

The string written between the two numbers (default ':').

Tags
throws
InvalidArgumentException

When the width or the height is zero or below.

example
use function oihana\core\maths\aspectRatio ;

echo aspectRatio( 1920 , 1080 ) ;        // "16:9"
echo aspectRatio( 1280 , 1080 ) ;        // "32:27"
echo aspectRatio( 1920 , 1080 , '/' ) ;  // "16/9"
echo aspectRatio( 1080 , 1080 ) ;        // "1:1"
author

Marc Alcaraz (ekameleon)

since
1.3.0
Return values
string —

The simplified ratio, e.g. "16:9".

bearing()

Calculates the initial bearing (sometimes referred to as forward azimuth) which if followed in a straight line along a great-circle arc will take you from the start point to the end point (in degrees).

bearing(float $latitude1, float $longitude1, float $latitude2, float $longitude2) : float
Parameters
$latitude1 : float

The first latitude coordinate in degrees.

$longitude1 : float

The first longitude coordinate in degrees.

$latitude2 : float

The second latitude coordinate in degrees.

$longitude2 : float

The second longitude coordinate in degrees.

Tags
example
$position1 = [ 'x' => 37.422045 , 'y' => -122.084347 ]; // Google HQ
$position2 = [ 'x' => 37.77493  , 'y' => -122.419416 ]; // San Francisco, CA

echo bearing($position1['x'], $position1['y'], $position2['x'], $position2['y']);
// 323.1477743368166
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
float —

The bearing in degrees from North.

cartesianToPolar()

Converts a cartesian vector to polar coordinates.

cartesianToPolar(array{x?: float|int, y?: float|int} $vector[, bool $degrees = true ][, bool $throwable = false ]) : array{angle: float, radius: float}
Parameters
$vector : array{x?: float|int, y?: float|int}

Cartesian coordinates with keys 'x' and 'y'.

$degrees : bool = true

Whether the returned angle should be in degrees (default: true).

$throwable : bool = false

Whether to throw an exception if keys are missing (default: false).

Tags
throws
InvalidArgumentException

if $throwable is true and required keys are missing.

example
$polar = cartesianToPolar(['x' => 0, 'y' => 5]);
// Returns: ['angle' => 90, 'radius' => 5]

$polar = cartesianToPolar(['x' => 1, 'y' => 1], false);
// Returns angle in radians
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
array{angle: float, radius: float} —

Polar coordinates with keys 'angle' and 'radius'.

ceilValue()

Rounds a number up to a count of decimal places.

ceilValue(int|float $value[, int $floatCount = 0 ]) : float

The ceiling of a number is the closest integer that is greater than or equal to it.

A decimal number is almost never exact in memory : 1.1 * 100 holds 110.00000000000001, and a naive ceil( $value * $r ) / $r climbs to 1.11. The scaled value is therefore rounded to six decimals before the ceiling is taken : a scaled value within one millionth of an integer is treated as sitting exactly on it, so only a real excess pushes the result up.

Parameters
$value : int|float

The number to round.

$floatCount : int = 0

The number of decimal places to round up to. A negative count is read as 0.

Tags
example
use function oihana\core\maths\ceilValue;

echo ceilValue( 4.1234 )    ; // 5
echo ceilValue( 4.1234 , 2 ) ; // 4.13
echo ceilValue( 4.9999 , 3 ) ; // 5
echo ceilValue( 1.1 , 2 )    ; // 1.1  — not 1.11 : the float noise is ignored
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
float —

The rounded number.

factorial()

Computes the factorial `n!` of a non-negative integer.

factorial(int $n) : int

factorial(0) is 1. The argument is capped at 20 because 21! exceeds PHP_INT_MAX and could no longer be represented exactly as an int.

Parameters
$n : int

A non-negative integer in the range [0, 20].

Tags
throws
InvalidArgumentException

If $n is negative or greater than 20.

example
use function oihana\core\maths\factorial;

echo factorial( 0 ) ; // 1
echo factorial( 5 ) ; // 120
echo factorial( 10 ) ; // 3628800
author

Marc Alcaraz (ekameleon)

since
1.0.9
Return values
int —

The factorial of $n.

fixAngle()

Normalize an angle in degrees to the range [0, 360).

fixAngle(float|int $angle) : float

If the input is not numeric (NaN, null, etc.), the function will return 0.

Parameters
$angle : float|int

The angle in degrees.

Tags
example
echo fixAngle(370);   // 10
echo fixAngle(-90);   // 270
echo fixAngle(720.5); // 0.5
echo fixAngle(NAN);   // 0
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
float —

The normalized angle between 0 (inclusive) and 360 (exclusive).

floorValue()

Rounds a number down to a count of decimal places.

floorValue(int|float $value[, int $floatCount = 0 ]) : float

The floor of a number is the closest integer that is less than or equal to it.

A decimal number is almost never exact in memory : 8.2 * 100 holds 819.9999999999999, and a naive floor( $value * $r ) / $r drops to 8.19. The scaled value is therefore rounded to six decimals before the floor is taken : a scaled value within one millionth of an integer is treated as sitting exactly on it, so only a real shortfall pushes the result down.

Parameters
$value : int|float

The number to round.

$floatCount : int = 0

The number of decimal places to round down to. A negative count is read as 0.

Tags
example
use function oihana\core\maths\floorValue;

echo floorValue( 4.9876 )     ; // 4
echo floorValue( 4.9876 , 2 ) ; // 4.98
echo floorValue( 4.1234 , 3 ) ; // 4.123
echo floorValue( 8.2 , 2 )    ; // 8.2  — not 8.19 : the float noise is ignored
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
float —

The rounded number.

gcd()

Calculate the Greatest Common Divisor (GCD) of two integers using the Euclidean algorithm.

gcd(int $a, int $b[, bool $throwable = false ]) : int

This function returns the absolute value of the GCD. If both numbers are zero, it either returns 0 or throws an exception depending on the $throwable parameter.

Parameters
$a : int

The first integer.

$b : int

The second integer.

$throwable : bool = false

If true, throws an exception when both numbers are zero.

Tags
throws
InvalidArgumentException

If both $a and $b are zero and $throwable is true.

example
echo gcd(48, 18); // Outputs: 6
echo gcd(-48, 18); // Outputs: 6
echo gcd(0, 5);    // Outputs: 5
echo gcd(0, 0);    // Outputs: 0
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
int —

The greatest common divisor of $a and $b.

haversine()

Calculate the great-circle distance between two points on a sphere using the Haversine formula.

haversine(float $latitude1, float $longitude1, float $latitude2, float $longitude2[, float $radius = 6371000 ][, int|null $precision = null ]) : float

This is commonly used for distances on Earth. It's faster than the Vincenty formula but less precise.

Parameters
$latitude1 : float

The latitude of the first point in degrees.

$longitude1 : float

The longitude of the first point in degrees.

$latitude2 : float

The latitude of the second point in degrees.

$longitude2 : float

The longitude of the second point in degrees.

$radius : float = 6371000

The radius of the sphere (default is Earth's mean radius: 6,371,000 meters).

$precision : int|null = null

Number of decimal places to round to. If null, returns full precision.

Tags
throws
InvalidArgumentException

If $precision is not null and is negative.

example
use function oihana\core\maths\haversine;

$pos1 = [ 37.422045, -122.084347 ] ; // Google HQ
$pos2 = [ 37.77493,  -122.419416 ] ; // San Francisco, CA

echo haversine( $pos1[0] , $pos1[1], $pos2[0] , $pos2[1] ) ;       // Full precision
echo haversine( $pos1[0] , $pos1[1], $pos2[0] , $pos2[1] , 6371000, 3 ); // Rounded to 3 decimals
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
float —

The distance between the two points in meters.

isPrime()

Tells whether an integer is a prime number.

isPrime(int $n) : bool

Any integer lower than 2 is not prime. The test uses 6k ± 1 trial division up to √n.

Parameters
$n : int

The integer to test.

Tags
example
use function oihana\core\maths\isPrime;

isPrime( 2 )  ; // true
isPrime( 17 ) ; // true
isPrime( 25 ) ; // false
isPrime( 1 )  ; // false
author

Marc Alcaraz (ekameleon)

since
1.0.9
Return values
bool —

true if $n is prime, false otherwise.

mean()

Computes the arithmetic mean (average) of a list of numbers.

mean(array<int, int|float> $values) : float
Parameters
$values : array<int, int|float>

A non-empty list of numeric values.

Tags
throws
InvalidArgumentException

If the array is empty.

example
use function oihana\core\maths\mean;

echo mean( [ 1 , 2 , 3 , 4 ] ) ; // 2.5
echo mean( [ 2 , 4 , 6 ] )      ; // 4.0
author

Marc Alcaraz (ekameleon)

since
1.0.9
Return values
float —

The arithmetic mean of the values.

median()

Computes the median (middle value) of a list of numbers.

median(array<int, int|float> $values) : float

The values are sorted numerically. For an odd number of values the middle one is returned ; for an even number, the average of the two central values is returned.

Parameters
$values : array<int, int|float>

A non-empty list of numeric values.

Tags
throws
InvalidArgumentException

If the array is empty.

example
use function oihana\core\maths\median;

echo median( [ 3 , 1 , 2 ] )     ; // 2.0
echo median( [ 4 , 1 , 3 , 2 ] ) ; // 2.5
author

Marc Alcaraz (ekameleon)

since
1.0.9
Return values
float —

The median of the values.

polarToCartesian()

Converts a polar coordinate to a cartesian vector.

polarToCartesian(array{angle?: float, radius?: float} $vector[, bool $degrees = true ][, bool $throwable = false ]) : array{x: float, y: float}
Parameters
$vector : array{angle?: float, radius?: float}

Polar coordinates with keys 'angle' and 'radius'. Both are optional — a missing one defaults to 0, or throws when $throwable is true.

$degrees : bool = true

Whether the angle is in degrees (default: true).

$throwable : bool = false

Whether to throw when the 'angle'/'radius' keys are missing (default: false).

Tags
throws
InvalidArgumentException

If $throwable is true and keys are missing.

example
use function oihana\core\maths\polarToCartesian;

// Example 1: normal usage
$polar = ['angle' => 45, 'radius' => 10];
$cartesian = polarToCartesian($polar) ;
print_r($cartesian);
// Output: ['x' => 7.0710678118655, 'y' => 7.0710678118655]

// Example 2: missing angle, throwable = false (default)
$polar2 = ['radius' => 5];
$cartesian2 = polarToCartesian($polar2) ;
print_r($cartesian2);
// Output: ['x' => 0, 'y' => 0]

// Example 3: missing angle, throwable = true
$polar3 = ['radius' => 5];
try
{
    $cartesian3 = polarToCartesian($polar3, true, true);
}
catch ( InvalidArgumentException $e )
{
    echo $e->getMessage();
}
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
array{x: float, y: float} —

Cartesian representation with keys 'x' and 'y'.

roundValue()

Rounds a number to a count of decimal places.

roundValue(int|float $value[, int $floatCount = 0 ]) : float

A decimal number is almost never exact in memory : 0.235 * 2.5 * 1000 holds 587.4999999999999, and a naive round( $value * $r ) / $r falls to 0.587. The scaled value is therefore rounded to six decimals first : a scaled value within one millionth of a half-way point is treated as sitting exactly on it, so it rounds the way the exact arithmetic would.

Parameters
$value : int|float

The number to round.

$floatCount : int = 0

The number of decimal places to round to. A negative count is read as 0.

Tags
example
use function oihana\core\maths\roundValue;

echo roundValue( 4.9876 )            ; // 5
echo roundValue( 4.9876 , 2 )        ; // 4.99
echo roundValue( 4.1234 , 3 )        ; // 4.123
echo roundValue( 0.235 * 2.5 , 3 )   ; // 0.588 — not 0.587 : the float noise is ignored
author

Marc Alcaraz (ekameleon)

since
1.0.0
Return values
float —

The rounded number.

shedFloatNoise()

Sheds the binary noise a computed figure carries, and rounds no business figure.

shedFloatNoise(int|float $value[, int $digits = 12 ][, int|float|null $scale = null ]) : float

Adding floats leaves an error that grows with the figure : a sum of two hundred thousand comes back as 202799.4000000001, a sum of forty five thousand as 45292.249999999985. A fixed count of decimals — ten, say — cleans the second and leaves the first, because the noise of a double sits at a relative distance of the value, not at a fixed decimal.

🔑 The scale follows the size of the value. The figure is rounded to a count of significant digits : twelve by default, where a double holds fifteen to seventeen — the last ones are left to the noise, and every decimal a source records survives, a quantity of 13039.42858, a weight of 55999.81828, a volume of 0.0073.

⚠️ Not a rounding. Two decimals on an amount or five on a quantity are business rules, written where the figure is shown or stored (roundValue()). This function only removes what an addition of floats left behind : a figure that was never computed needs none of it.

🚨 A sum whose terms cancel needs the scale of its terms. The noise an addition leaves is relative to the size of the figures added, not to the size of the result. When they nearly cancel, the result is tiny and twelve of its own digits are the noise itself : 1000.01 - 1000.00 holds 0.009999999999990905. Given the size of the largest term as $scale, the digits are reckoned on it — twelve at the scale of a thousand are eight decimals — and the figure comes back as 0.01. The larger of the value and the scale is the one used, so a scale never keeps more digits than the value alone would.

The result is never a negative zero : a dust below zero shed to nothing is 0.0, not -0.0. An infinite figure and a NaN are answered as they are.

Parameters
$value : int|float

The computed figure.

$digits : int = 12

How many significant digits to keep. Default 12.

$scale : int|float|null = null

The size the digits are reckoned on — the largest term of a sum. Default null : the size of the value itself.

Tags
example
use function oihana\core\maths\shedFloatNoise;

echo shedFloatNoise( 0.1 + 0.2 )          ; // 0.3
echo shedFloatNoise( 202799.4000000001 )  ; // 202799.4
echo shedFloatNoise( 45292.249999999985 ) ; // 45292.25
echo shedFloatNoise( 13039.42858 )        ; // 13039.42858 — a real decimal survives
echo shedFloatNoise( 0.0073 )             ; // 0.0073

// Terms that cancel : the result alone is too small to say where the noise starts.
echo shedFloatNoise( 1000.01 - 1000.00 )                   ; // 0.00999999999999
echo shedFloatNoise( 1000.01 - 1000.00 , scale: 1000.01 )  ; // 0.01
echo shedFloatNoise( 1000.00 - 999.99 - 0.01 , scale: 1000 ) ; // 0
author

Marc Alcaraz (ekameleon)

since
1.3.0
Return values
float —

The figure, rid of its noise.

stddev()

Computes the standard deviation of a list of numbers.

stddev(array<int, int|float> $values[, bool $sample = false ]) : float

The standard deviation is the square root of the variance(). By default the population standard deviation is returned ; when $sample is true, the sample standard deviation is returned (Bessel's correction, N - 1).

Parameters
$values : array<int, int|float>

A list of numeric values (at least one for population, two for sample).

$sample : bool = false

Whether to compute the sample standard deviation (N - 1) instead of the population one (N).

Tags
throws
InvalidArgumentException

If the array is empty, or has fewer than two values when $sample is true.

example
use function oihana\core\maths\stddev;

echo stddev( [ 2 , 4 , 4 , 4 , 5 , 5 , 7 , 9 ] )        ; // 2.0   (population)
echo stddev( [ 2 , 4 , 4 , 4 , 5 , 5 , 7 , 9 ] , true ) ; // ~2.138 (sample)
author

Marc Alcaraz (ekameleon)

since
1.0.9
Return values
float —

The standard deviation of the values.

variance()

Computes the variance of a list of numbers.

variance(array<int, int|float> $values[, bool $sample = false ]) : float

By default the population variance is returned (sum of squared deviations divided by N). When $sample is true, the sample variance is returned instead (divided by N - 1, Bessel's correction).

Parameters
$values : array<int, int|float>

A list of numeric values (at least one for population, two for sample).

$sample : bool = false

Whether to compute the sample variance (N - 1) instead of the population one (N).

Tags
throws
InvalidArgumentException

If the array is empty, or has fewer than two values when $sample is true.

example
use function oihana\core\maths\variance;

echo variance( [ 2 , 4 , 4 , 4 , 5 , 5 , 7 , 9 ] )        ; // 4.0  (population)
echo variance( [ 2 , 4 , 4 , 4 , 5 , 5 , 7 , 9 ] , true ) ; // ~4.571 (sample)
author

Marc Alcaraz (ekameleon)

since
1.0.9
Return values
float —

The variance of the values.

On this page

Search results