18 public static function add($value,$add = 1,$base = null,$upper = null){
19 if($upper === null) $upper = ($base > 10) && (strtoupper($value) == $value);
20 if($base) $value = base_convert($value,$base,10);
22 if($base) $value = base_convert($value,10,$base);
23 if($upper) $value = strtoupper($value);
34 switch(strtolower(substr($size,-1))){
35 case 'e': $factor <<= 10;
36 case 'p': $factor <<= 10;
37 case 't': $factor <<= 10;
38 case 'g': $factor <<= 10;
39 case 'm': $factor <<= 10;
40 case 'k': $factor <<= 10;
42 return $factor * (int)$size;
53 public static function formatBytes($size,$decimals = 1,$dec_point =
'.',$thousands_sep =
',',$unit_sep =
' '){
55 $units = [
'kb',
'Mb',
'Gb',
'Tb'];
56 if($size < 1024) $decimals = 0;
57 else while(($size >= 1024) && $units){
59 $unit = array_shift($units);
61 return number_format($size,$decimals,$dec_point,$thousands_sep) . $unit_sep . $unit;
70 $numbers = [
'M' => 1000,
'CM' => 900,
'D' => 500,
'CD' => 400,
'C' => 100,
'XC' => 90,
'L' => 50,
'XL' => 40,
'X' => 10,
'IX' => 9,
'V' => 5,
'IV' => 4,
'I' => 1];
71 while($value > 0)
foreach($numbers as $roman => $number)
if($value >= $number){
80 return $value * 1.8 + 32;
84 return ($value - 32) / 1.8;
93 public static function units($value,$units,$tolerance = 0){
94 $result = $counts = [];
95 foreach(array_reverse(array_keys(\
Rsi\Record::sort($units))) as $unit){
96 $count = $value / $units[$unit];
97 if($unit) $count = floor($count);
98 if($count || $counts) $counts[$unit] = $count;
99 if(($value -= $count * $units[$unit]) < $tolerance)
break;
101 foreach($units as $unit => $count)
if(array_key_exists($unit,$counts)) $result[$unit] = $counts[$unit];
110 public static function fraction($value,$tolerance = 0.000001){
111 $num = $prev_den = 1;
112 $den = $prev_num = 0;
113 $sign = $value < 0 ? -1 : 1;
114 $frac = 1 / ($value = abs($value));
117 $rest = floor($frac);
118 $prev = $num; $num = $rest * $num + $prev_num; $prev_num = $prev;
119 $prev = $den; $den = $rest * $den + $prev_den; $prev_den = $prev;
120 $frac = $frac - $rest;
122 while(abs($value - $num / $den) > $value * $tolerance);
123 return [$sign * $num,$den];
131 $number =
'-?\\d+(?:\\.\\d+)?';
132 $operators = [
'^',
'*',
'/',
'%',
'+',
'-',
'>',
'>=',
'<',
'<=',
'==',
'!='];
134 'decbin',
'dechex',
'decoct',
'deg2rad',
'rad2deg',
135 'abs',
'floor',
'ceil',
'sqrt',
'exp',
'ln',
'log',
'pi',
136 'sin',
'sinh',
'arcsin',
'asin',
'arcsinh',
'asinh',
137 'cos',
'cosh',
'arccos',
'acos',
'arccosh',
'acosh',
138 'tan',
'tanh',
'arctan',
'atan',
'arctanh',
'atanh' 141 'min',
'max',
'count',
'sum',
'unique',
'filter',
'product' 144 $expr = substr(preg_replace(
'/(?<![\\(' . preg_quote(implode($operators),
'/') .
'])\\-/',
'- ',
'^' . $expr),1);
147 if(preg_match_all(
'/\'(\\d{4})- (\\d{1,2})- (\\d{1,2})/',$expr,$matches,PREG_SET_ORDER))
148 foreach($matches as list($full,$year,$month,$day))
149 $expr = str_replace($full,
"'$year-" . Str::pad($month,2) .
'-' . Str::pad($day,2),$expr);
152 $expr = str_replace(
'π',
'pi()',$expr);
153 while(preg_match(
'/(\\w*)\\(([^\\(\\)]*)\\)/',$expr,$match)){
154 list($full,$func_name,$params) = $match;
156 $params = explode(
',',$params);
158 if(in_array($func_name,$functions)) $value = call_user_func($func_name,$params[0] ===
'' ? null : self::evaluate($params[0]));
159 elseif(in_array($func_name,$array_functions)){
160 if(is_array($value = call_user_func(function_exists($array_name =
'array_' . $func_name) ? $array_name : $func_name,array_map([
'self',
'evaluate'],$params))))
161 $value = implode(
',',$value);
163 else switch($func_name){
165 if(($value = $params[0]) ===
'') $value = time();
166 elseif(substr($value = $params[0],0,1) ==
"'") $value = strtotime(substr($value,1,-1));
167 if($modifier = $params[1] ?? null) $value = strtotime($modifier,$value);
170 if(!is_numeric($value = date($params[1] ??
'Y-m-d',self::evaluate($params[0]))))
return $value;
172 case 'frac': $value = fmod(self::evaluate($params[0]),1);
break;
173 case 'fracnum': $value = self::fraction(self::evaluate($params[0]),$params[1] ?? 0.000001)[0];
break;
174 case 'fracden': $value = self::fraction(self::evaluate($params[0]),$params[1] ?? 0.000001)[1];
break;
175 case 'round': $value = round(self::evaluate($params[0]),$params[1] ?? 0);
break;
176 case 'rand': $value = rand(self::evaluate($params[0]),self::evaluate($params[1] ?? 0));
break;
177 case 'degc2f': $value = self::celsiusToFahrenheit(self::evaluate($params[0]));
break;
178 case 'degf2c': $value = self::fahrenheitToCelsius(self::evaluate($params[0]));
break;
179 case 'avg':
return ($array = array_map([
'self',
'evaluate'],$params)) ? array_sum($array) / count($array) : 0;
break;
180 case 'first': $value = self::evaluate(array_shift($params));
break;
181 case 'last': $value = self::evaluate(array_pop($params));
break;
182 case 'exists': $value = array_search(self::evaluate(array_shift($params)),array_map([
'self',
'evaluate'],$params)) ===
false ? 0 : 1;
break;
183 case 'if': $value = self::evaluate($params[0]) ? self::evaluate($params[1] ?? 1) : self::evaluate($params[2] ?? 0);
break;
184 default:
throw new \Exception(
"Unknown function '$func_name'");
186 $expr = str_replace($full,$value,$expr);
188 else $expr = str_replace($full,self::evaluate($params),$expr);
192 foreach($operators as $operator)
while(preg_match(
'/(' . $number .
')\\s*' . preg_quote($operator,
'/') .
'\\s*(' . $number .
')/',$expr,$match)){
193 list($full,$a,$b) = $match;
196 case '^': $value = pow($a,$b);
break;
197 case '*': $value = $a * $b;
break;
198 case '/': $value = $a / $b;
break;
199 case '%': $value = $a % $b;
break;
200 case '+': $value = $a + $b;
break;
201 case '-': $value = $a - $b;
break;
202 case '>': $value = intval($a > $b);
break;
203 case '>=': $value = intval($a >= $b);
break;
204 case '<': $value = intval($a < $b);
break;
205 case '<=': $value = intval($a <= $b);
break;
206 case '==': $value = intval($a == $b);
break;
207 case '!=': $value = intval($a != $b);
break;
208 default:
throw new \Exception(
"Unknown operator '$operator'");
210 $expr = str_replace($full,$value,$expr);
static evaluate($expr)
Evaluate a mathamatical expression.
static toRoman($value)
Format a number as a Roman number.
static fahrenheitToCelsius($value)
static shorthandBytes($size)
Returns the size in bytes for shorthand notations (e.g.
static add($value, $add=1, $base=null, $upper=null)
Add a value to a non-decimal number.
Helpers for numbers of all sorts.
static units($value, $units, $tolerance=0)
Split a value into different units.
static celsiusToFahrenheit($value)
static fraction($value, $tolerance=0.000001)
Turn a decimal number into a fraction.
static formatBytes($size, $decimals=1, $dec_point='.', $thousands_sep=',', $unit_sep=' ')
Formats a size in bytes to its shorthand format.