123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- <?php
- namespace MathPHP;
- use MathPHP\Exception\BadParameterException;
- class Arithmetic
- {
- /**
- * Calculate any nᵗʰ root of a value: ⁿ√x
- * Equivalent to x¹/ⁿ
- *
- * nᵗʰ root of a number x is a number r which, when raised to the power n yields x:
- *
- * Use the the PHP pow function if it is an even root or if $x is positive.
- * If $x is negative and it is an odd root, we can extend the native function.
- *
- * @param float $x value to find the root of
- * @param int $nᵗʰ root (magnitude of the root - 2 for square root, 3 for cube root, etc.)
- *
- * @return float
- */
- public static function root(float $x, int $nᵗʰ): float
- {
- if ($x >= 0 || $nᵗʰ % 2 === 0) {
- return \pow($x, 1 / $nᵗʰ);
- }
- return - \pow(\abs($x), 1 / $nᵗʰ);
- }
- /**
- * Cube root ³√x
- * This function is necessary because pow($x, 1/3) returns NAN for negative values.
- * PHP does not have the cbrt built-in function.
- *
- * @param float $x
- *
- * @return float
- */
- public static function cubeRoot(float $x): float
- {
- return self::root($x, 3);
- }
- /**
- * Integer square root |_√x_|
- * The positive integer which is the greatest integer less than or equal to the square root
- * https://en.wikipedia.org/wiki/Integer_square_root
- *
- * @param float $x
- *
- * @return int
- *
- * @throws BadParameterException
- */
- public static function isqrt(float $x): int
- {
- if ($x < 0) {
- throw new Exception\BadParameterException("x must be non-negative for isqrt - got $x");
- }
- return (int)\floor(\sqrt($x));
- }
- /**
- * Digit sum
- * Sum of all an integer's digits.
- * https://en.wikipedia.org/wiki/Digit_sum
- *
- * log x 1
- * ∑ -- (x mod bⁿ⁺¹ - x mod bⁿ)
- * ⁿ⁼⁰ bⁿ
- *
- * Example (base 10): 5031 = 5 + 0 + 3 + 1 = 9
- * Example (base 2): 0b1010 = 1 + 0 + 1 + 0 = 2
- *
- * @param int $x
- * @param int $b Base (Default is base 10)
- *
- * @return int
- */
- public static function digitSum(int $x, int $b = 10): int
- {
- $logx = \log($x, $b);
- $∑1/bⁿ⟮x mod bⁿ⁺¹ − x mod bⁿ⟯ = 0;
- for ($n = 0; $n <= $logx; $n++) {
- $∑1/bⁿ⟮x mod bⁿ⁺¹ − x mod bⁿ⟯ += \intdiv(($x % \pow($b, $n + 1)) - ($x % $b ** $n), ($b ** $n));
- }
- return $∑1/bⁿ⟮x mod bⁿ⁺¹ − x mod bⁿ⟯;
- }
- /**
- * Digital root (iterated digit sum, repeated digital sum)
- * The single digit value obtained by an iterative process of summing digits,
- * on each iteration using the result from the previous iteration to compute a digit sum.
- * The process continues until a single-digit number is reached.
- * https://en.wikipedia.org/wiki/Digital_root
- *
- * Example: 65,536 is 7, because 6 + 5 + 5 + 3 + 6 = 25 and 2 + 5 = 7
- *
- * @param int $x
- *
- * @return int
- */
- public static function digitalRoot(int $x): int
- {
- $root = $x;
- while ($root >= 10) {
- $root = self::digitSum($root);
- }
- return $root;
- }
- /**
- * Test if two numbers are almost equal, within a tolerance ε
- *
- * @param float $x
- * @param float $y
- * @param float $ε tolerance
- *
- * @return bool true if the numbers are equal within a tolerance; false if they are not
- */
- public static function almostEqual(float $x, float $y, $ε = 0.000000000001): bool
- {
- return \abs($x - $y) <= $ε;
- }
- /**
- * Returns the magnitude value with the sign of the sign number
- *
- * @param float $magnitude
- * @param float $sign
- *
- * @return float $magnitude with the sign of $sign
- */
- public static function copySign(float $magnitude, float $sign): float
- {
- return $sign >= 0
- ? \abs($magnitude)
- : -\abs($magnitude);
- }
- /**
- * Modulo (Binary operation)
- *
- * Modulo is different from the remainder function.
- * The PHP % operator is the remainder function, where the result has the same sign as the dividend.
- * The mod function's result has the same sign as the divisor.
- *
- * For positive dividends and divisors, the modulo function is the same as the remainder (%) operator.
- * For negative dividends or divisors, the modulo function has different behavior than the remainder (%) operator.
- *
- * a mod n
- * a - n ⌊a/n⌋ for n ≠ 0
- * a for n = 0
- * where
- * a is the dividend (integer)
- * n is the divisor, also known as the modulus (integer)
- * ⌊⌋ is the floor function
- *
- * https://en.wikipedia.org/wiki/Modulo_operation
- * https://en.wikipedia.org/wiki/Modulo_(mathematics)
- * Knuth, Donald. E. (1972). The Art of Computer Programming. Volume 1 Fundamental Algorithms. Addison-Wesley.
- * Graham, Knuth, Patashnik (1994). Concrete Mathematics, A Foundation For Computer Science. Addison-Wesley.
- *
- * @param int $a dividend
- * @param int $n divisor, also known as the modulus
- *
- * @return int
- */
- public static function modulo(int $a, int $n): int
- {
- if ($n === 0) {
- return $a;
- }
- return (int)($a - $n * \floor($a / $n));
- }
- }
|