ILIAS  Release_4_2_x_branch Revision 61807
 All Data Structures Namespaces Files Functions Variables Groups Pages
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 
32 class ilMath
33 {
34  /*
35  * Add two numbers
36  */
37  public static function _add($left_operand, $right_operand, $scale = 50)
38  {
39  if (function_exists("bcadd"))
40  {
41  return bcadd(ilMath::exp2dec($left_operand), ilMath::exp2dec($right_operand), $scale);
42  }
43  else
44  {
45  $res = $left_operand + $right_operand;
46  if (is_numeric($scale)) $res = round($res, $scale);
47  return $res;
48  }
49  }
50 
51  /*
52  * Compare two numbers
53  */
54  public static function _comp($left_operand, $right_operand, $scale = 50)
55  {
56  if (function_exists("bccomp"))
57  {
58  return bccomp(ilMath::exp2dec($left_operand), ilMath::exp2dec($right_operand), $scale);
59  }
60  else
61  {
62  if (is_numeric($scale))
63  {
64  $left_operand = round($left_operand, $scale);
65  $right_operand = round($right_operand, $scale);
66  }
67  if ($left_operand == $right_operand) return 0;
68  if ($left_operand > $right_operand) return 1;
69  return -1;
70  }
71  }
72 
73  /*
74  * Divide two numbers
75  */
76  public static function _div($left_operand, $right_operand, $scale = 50)
77  {
78  if (function_exists("bcdiv"))
79  {
80  return bcdiv(ilMath::exp2dec($left_operand), ilMath::exp2dec($right_operand), $scale);
81  }
82  else
83  {
84  if ($right_operand == 0) return NULL;
85  $res = $left_operand / $right_operand;
86  if (is_numeric($scale)) $res = round($res, $scale);
87  return $res;
88  }
89  }
90 
91  /*
92  * Get modulus of two numbers
93  */
94  public static function _mod($left_operand, $modulus)
95  {
96  if (function_exists("bcmod"))
97  {
98  return bcmod(ilMath::exp2dec($left_operand), $modulus);
99  }
100  else
101  {
102  return $left_operand % $right_operand;
103  }
104  }
105 
106  /*
107  * Multiplicate two numbers
108  */
109  public static function _mul($left_operand, $right_operand, $scale = 50)
110  {
111  if (function_exists("bcmul"))
112  {
113  return bcmul(ilMath::exp2dec($left_operand), ilMath::exp2dec($right_operand), $scale);
114  }
115  else
116  {
117  $res = $left_operand * $right_operand;
118  if (is_numeric($scale)) $res = round($res, $scale);
119  return $res;
120  }
121  }
122 
123  /*
124  * Raise a number to another
125  */
126  public static function _pow($left_operand, $right_operand, $scale = 50)
127  {
128  if (function_exists("bcpow"))
129  {
130  return bcpow(ilMath::exp2dec($left_operand), ilMath::exp2dec($right_operand), $scale);
131  }
132  else
133  {
134  $res = pow($left_operand, $right_operand);
135  if (is_numeric($scale)) $res = round($res, $scale);
136  return $res;
137  }
138  }
139 
140  /*
141  * Get the square root of a number
142  */
143  public static function _sqrt($operand, $scale = 50)
144  {
145  if (function_exists("bcsqrt"))
146  {
147  return bcsqrt(ilMath::exp2dec($operand), $scale);
148  }
149  else
150  {
151  $res = sqrt($operand);
152  if (is_numeric($scale)) $res = round($res, $scale);
153  return $res;
154  }
155  }
156 
157  /*
158  * Subtract two numbers
159  */
160  public static function _sub($left_operand, $right_operand, $scale = 50)
161  {
162  if (function_exists("bcsub"))
163  {
164  return bcsub(ilMath::exp2dec($left_operand), ilMath::exp2dec($right_operand), $scale);
165  }
166  else
167  {
168  $res = $left_operand - $right_operand;
169  if (is_numeric($scale)) $res = round($res, $scale);
170  return $res;
171  }
172  }
173 
174  /*
175  * Converts numbers in the form "1.5e4" into decimal notation
176  * Only available for bcmath
177  */
178  function exp2dec($float_str)
179  {
180  // make sure its a standard php float string (i.e. change 0.2e+2 to 20)
181  // php will automatically format floats decimally if they are within a certain range
182  $original = $float_str; // store original float, so we can return a float keeping the pecision when possible
183  $float_str = (string)((float)($float_str));
184  $float_str = str_replace(",", ".", $float_str); // convert ',' to '.' (float casting was locale sensitive)
185 
186  // if there is an E in the float string
187  if(($pos = strpos(strtolower($float_str), 'e')) !== false)
188  {
189  // get either side of the E, e.g. 1.6E+6 => exp E+6, num 1.6
190  $exp = substr($float_str, $pos+1);
191  $num = substr($float_str, 0, $pos);
192 
193  // strip off num sign, if there is one, and leave it off if its + (not required)
194  if((($num_sign = $num[0]) === '+') || ($num_sign === '-')) $num = substr($num, 1);
195  else $num_sign = '';
196  if($num_sign === '+') $num_sign = '';
197 
198  // strip off exponential sign ('+' or '-' as in 'E+6') if there is one, otherwise throw error, e.g. E+6 => '+'
199  if((($exp_sign = $exp[0]) === '+') || ($exp_sign === '-')) $exp = substr($exp, 1);
200  else trigger_error("Could not convert exponential notation to decimal notation: invalid float string '$float_str'", E_USER_ERROR);
201 
202  // 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
203  $right_dec_places = (($dec_pos = strpos($num, '.')) === false) ? 0 : strlen(substr($num, $dec_pos+1));
204  // 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
205  $left_dec_places = ($dec_pos === false) ? strlen($num) : strlen(substr($num, 0, $dec_pos));
206 
207  // work out number of zeros from exp, exp sign and dec places, e.g. exp 6, exp sign +, dec places 1 => num zeros 5
208  if($exp_sign === '+') $num_zeros = $exp - $right_dec_places;
209  else $num_zeros = $exp - $left_dec_places;
210 
211  // build a string with $num_zeros zeros, e.g. '0' 5 times => '00000'
212  $zeros = str_pad('', $num_zeros, '0');
213 
214  // strip decimal from num, e.g. 1.6 => 16
215  if($dec_pos !== false) $num = str_replace('.', '', $num);
216 
217  // if positive exponent, return like 1600000
218  if($exp_sign === '+') return $num_sign.$num.$zeros;
219  // if negative exponent, return like 0.0000016
220  else return $num_sign.'0.'.$zeros.$num;
221  }
222  // otherwise, assume already in decimal notation and return
223  else return $original;
224  }
225 }
226 ?>