ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilMath.php
Go to the documentation of this file.
1<?php
2/*
3 +-----------------------------------------------------------------------------+
4 | ILIAS open source |
5 +-----------------------------------------------------------------------------+
6 | Copyright (c) 1998-2006 ILIAS open source, University of Cologne |
7 | |
8 | This program is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU General Public License |
10 | as published by the Free Software Foundation; either version 2 |
11 | of the License, or (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 +-----------------------------------------------------------------------------+
22*/
23
32class ilMath
33{
34 /*
35 * Add two numbers
36 */
37 public static function _add($left_operand, $right_operand, $scale = 50)
38 {
39 $left_operand=ilMath::bcconv($left_operand);
40 $right_operand=ilMath::bcconv($right_operand);
41 $scale=ilMath::bcconv($scale);
42
43 if (function_exists("bcadd"))
44 {
45 return bcadd($left_operand, $right_operand, $scale);
46 }
47 else
48 {
49 $res = $left_operand + $right_operand;
50 if (is_numeric($scale)) $res = round($res, $scale);
51 return $res;
52 }
53 }
54
55 /*
56 * Compare two numbers
57 */
58 public static function _comp($left_operand, $right_operand, $scale = 50)
59 {
60 $left_operand=ilMath::bcconv($left_operand);
61 $right_operand=ilMath::bcconv($right_operand);
62 $scale=ilMath::bcconv($scale);
63
64 if (function_exists("bccomp"))
65 {
66 return bccomp($left_operand, $right_operand, $scale);
67 }
68 else
69 {
70 if (is_numeric($scale))
71 {
72 $left_operand = round($left_operand, $scale);
73 $right_operand = round($right_operand, $scale);
74 }
75 if ($left_operand == $right_operand) return 0;
76 if ($left_operand > $right_operand) return 1;
77 return -1;
78 }
79 }
80
81 /*
82 * Divide two numbers
83 */
84 public static function _div($left_operand, $right_operand, $scale = 50)
85 {
86 $left_operand=ilMath::bcconv($left_operand);
87 $right_operand=ilMath::bcconv($right_operand);
88 $scale=ilMath::bcconv($scale);
89
90 if (function_exists("bcdiv"))
91 {
92 return bcdiv($left_operand, $right_operand, $scale);
93 }
94 else
95 {
96 if ($right_operand == 0) return NULL;
97 $res = $left_operand / $right_operand;
98 if (is_numeric($scale)) $res = round($res, $scale);
99 return $res;
100 }
101 }
102
103 /*
104 * Get modulus of two numbers
105 */
106 public static function _mod($left_operand, $modulus)
107 {
108 $left_operand=ilMath::bcconv($left_operand);
109 $modulus=ilMath::bcconv($modulus);
110
111 if (function_exists("bcmod"))
112 {
113 return bcmod($left_operand, $modulus);
114 }
115 else
116 {
117 return $left_operand % $modulus;
118 }
119 }
120
121 /*
122 * Multiplicate two numbers
123 */
124 public static function _mul($left_operand, $right_operand, $scale = 50)
125 {
126 $left_operand=ilMath::bcconv($left_operand);
127 $right_operand=ilMath::bcconv($right_operand);
128 $scale=ilMath::bcconv($scale);
129
130 if (function_exists("bcmul"))
131 {
132 return bcmul($left_operand, $right_operand, $scale);
133 }
134 else
135 {
136 $res = $left_operand * $right_operand;
137 if (is_numeric($scale)) $res = round($res, $scale);
138 return $res;
139 }
140 }
141
142 /*
143 * Raise a number to another
144 */
145 public static function _pow($left_operand, $right_operand, $scale = 50)
146 {
147 $left_operand=ilMath::bcconv($left_operand);
148 $right_operand=ilMath::bcconv($right_operand);
149 $scale=ilMath::bcconv($scale);
150
151 if(function_exists("bcpow"))
152 {
153 // bcpow() only supports exponents less than or equal to 2^31-1.
154 // Also, bcpow() does not support decimal numbers.
155 // If you have scale set to 0, then the exponent is converted to an integer; otherwise an error is generated.
156 $left_operand_dec = ilMath::exp2dec($left_operand);
157 $right_operand_dec = ilMath::exp2dec($right_operand);
158
159 $is_exponent_decimal_number = strpos($right_operand_dec, '.') !== false;
160
161 // bcpow does NOT support decimal exponents
162 if(!$is_exponent_decimal_number)
163 {
164 return bcpow($left_operand_dec, $right_operand_dec, $scale);
165 }
166 }
167
168 $res = pow($left_operand, $right_operand);
169 if (is_numeric($scale)) $res = round($res, $scale);
170 return $res;
171 }
172
173 /*
174 * Get the square root of a number
175 */
176 public static function _sqrt($operand, $scale = 50)
177 {
178 $operand=ilMath::bcconv($operand);
179 $scale=ilMath::bcconv($scale);
180
181 if (function_exists("bcsqrt"))
182 {
183 return bcsqrt($operand, $scale);
184 }
185 else
186 {
187 $res = sqrt($operand);
188 if (is_numeric($scale)) $res = round($res, $scale);
189 return $res;
190 }
191 }
192
193 /*
194 * Subtract two numbers
195 */
196 public static function _sub($left_operand, $right_operand, $scale = 50)
197 {
198 $left_operand=ilMath::bcconv($left_operand);
199 $right_operand=ilMath::bcconv($right_operand);
200 $scale=ilMath::bcconv($scale);
201
202 if (function_exists("bcsub"))
203 {
204 return bcsub($left_operand, $right_operand, $scale);
205 }
206 else
207 {
208 $res = $left_operand - $right_operand;
209 if (is_numeric($scale)) $res = round($res, $scale);
210 return $res;
211 }
212 }
213
214 /*
215 * Converts numbers in the form "1.5e4" into decimal notation
216 * Only available for bcmath
217 */
218 function exp2dec($float_str)
219 {
220 // make sure its a standard php float string (i.e. change 0.2e+2 to 20)
221 // php will automatically format floats decimally if they are within a certain range
222 $original = $float_str; // store original float, so we can return a float keeping the pecision when possible
223 $float_str = (string)((float)($float_str));
224 $float_str = str_replace(",", ".", $float_str); // convert ',' to '.' (float casting was locale sensitive)
225
226 // if there is an E in the float string
227 if(($pos = strpos(strtolower($float_str), 'e')) !== false)
228 {
229 // get either side of the E, e.g. 1.6E+6 => exp E+6, num 1.6
230 $exp = substr($float_str, $pos+1);
231 $num = substr($float_str, 0, $pos);
232
233 // strip off num sign, if there is one, and leave it off if its + (not required)
234 if((($num_sign = $num[0]) === '+') || ($num_sign === '-')) $num = substr($num, 1);
235 else $num_sign = '';
236 if($num_sign === '+') $num_sign = '';
237
238 // strip off exponential sign ('+' or '-' as in 'E+6') if there is one, otherwise throw error, e.g. E+6 => '+'
239 if((($exp_sign = $exp[0]) === '+') || ($exp_sign === '-')) $exp = substr($exp, 1);
240 else trigger_error("Could not convert exponential notation to decimal notation: invalid float string '$float_str'", E_USER_ERROR);
241
242 // get the number of decimal places to the right of the decimal point (or 0 if there is no dec point), e.g., 1.6 => 1
243 $right_dec_places = (($dec_pos = strpos($num, '.')) === false) ? 0 : strlen(substr($num, $dec_pos+1));
244 // get the number of decimal places to the left of the decimal point (or the length of the entire num if there is no dec point), e.g. 1.6 => 1
245 $left_dec_places = ($dec_pos === false) ? strlen($num) : strlen(substr($num, 0, $dec_pos));
246
247 // work out number of zeros from exp, exp sign and dec places, e.g. exp 6, exp sign +, dec places 1 => num zeros 5
248 if($exp_sign === '+') $num_zeros = $exp - $right_dec_places;
249 else $num_zeros = $exp - $left_dec_places;
250
251 // build a string with $num_zeros zeros, e.g. '0' 5 times => '00000'
252 $zeros = str_pad('', $num_zeros, '0');
253
254 // strip decimal from num, e.g. 1.6 => 16
255 if($dec_pos !== false) $num = str_replace('.', '', $num);
256
257 // if positive exponent, return like 1600000
258 if($exp_sign === '+') return $num_sign.$num.$zeros;
259 // if negative exponent, return like 0.0000016
260 else return $num_sign.'0.'.$zeros.$num;
261 }
262 // otherwise, assume already in decimal notation and return
263 else return $original;
264 }
265
266 public static function isCoprimeFraction($numerator, $denominator)
267 {
268 $gcd = self::getGreatestCommonDivisor(abs($numerator), abs($denominator));
269
270 return $gcd == 1 ? true : false;
271 }
272
273 public static function getGreatestCommonDivisor($a, $b)
274 {
275 if ($b > 0)
276 {
277 return self::getGreatestCommonDivisor($b, $a % $b);
278 }
279 else
280 {
281 return $a;
282 }
283 }
284
285 public static function _round($value, $precision = 0)
286 {
287 return number_format($value, $precision, '.', '');
288 }
289
290 public static function _equals($value1, $value2, $scale)
291 {
292 return self::_comp($value1, $value2, $scale) === 0;
293 }
294
301 private static function bcconv($fNumber)
302 {
303 $fNumber=ilMath::exp2dec($fNumber);
304 $locale_info = localeconv();
305 if($locale_info["decimal_point"] != ".")
306 {
307 $sAppend = '';
308 $iDecimals = ini_get('precision') - floor(log10(abs($fNumber)));
309 if (0 > $iDecimals)
310 {
311 $fNumber *= pow(10, $iDecimals);
312 $sAppend = str_repeat('0', -$iDecimals);
313 $iDecimals = 0;
314 }
315 return number_format($fNumber, $iDecimals, '.', '').$sAppend;
316 }
317 return $fNumber;
318 }
319}
320?>
Class ilMath.
static isCoprimeFraction($numerator, $denominator)
static _mod($left_operand, $modulus)
static _comp($left_operand, $right_operand, $scale=50)
static _mul($left_operand, $right_operand, $scale=50)
static _round($value, $precision=0)
static bcconv($fNumber)
static _sqrt($operand, $scale=50)
static _div($left_operand, $right_operand, $scale=50)
static _pow($left_operand, $right_operand, $scale=50)
static _equals($value1, $value2, $scale)
static getGreatestCommonDivisor($a, $b)
static _sub($left_operand, $right_operand, $scale=50)
exp2dec($float_str)
static _add($left_operand, $right_operand, $scale=50)