ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
class.ilMathBaseAdapter.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2017 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once 'Services/Math/interfaces/interface.ilMathAdapter.php';
5 
10 abstract class ilMathBaseAdapter implements ilMathAdapter
11 {
18  public function applyScale($number, $scale = null)
19  {
20  if (is_numeric($number)) {
21  $scale = (int) $scale;
22 
23  $number = $this->exp2dec($number);
24  if (strpos($number, '.') === false) {
25  $number_of_decimals = 0;
26  } else {
27  $number_of_decimals = strlen(substr($number, strpos($number, '.') + 1));
28  }
29 
30  if ($number_of_decimals > 0 && $number_of_decimals < $scale) {
31  $number = str_pad($number, $scale - $number_of_decimals, '0');
32  } elseif ($number_of_decimals > $scale) {
33  $number = substr($number, 0, -($number_of_decimals - $scale));
34  }
35  }
36 
37  return $number;
38  }
39 
43  public function round($value, $precision = 0)
44  {
45  return number_format($value, $precision, '.', '');
46  }
47 
51  public function equals($left_operand, $right_operand, $scale = null)
52  {
53  return $this->comp($left_operand, $right_operand, $scale) === 0;
54  }
55 
62  protected function normalize($number)
63  {
64  if (null === $number) {
65  return $number;
66  }
67 
68  $number = str_replace(' ', '', $number);
69  $number = $this->exp2dec($number);
70  $locale_info = localeconv();
71 
72  if ($locale_info['decimal_point'] != '.') {
73  $append = '';
74  $number_of_decimals = (int) ini_get('precision') - (int) floor(log10(abs($number)));
75  if (0 > $number_of_decimals) {
76  $number *= pow(10, $number_of_decimals);
77  $append = str_repeat('0', -$number_of_decimals);
78  $number_of_decimals = 0;
79  }
80 
81  return number_format($number, $number_of_decimals, '.', '') . $append;
82  }
83 
84  return $number;
85  }
86 
92  protected function exp2dec($float_str)
93  {
94  // make sure its a standard php float string (i.e. change 0.2e+2 to 20)
95  // php will automatically format floats decimally if they are within a certain range
96  $original = $float_str; // store original float, so we can return a float keeping the pecision when possible
97  $float_str = (string) ((float) ($float_str));
98  $float_str = str_replace(",", ".", $float_str); // convert ',' to '.' (float casting was locale sensitive)
99 
100  // if there is an E in the float string
101  if (($pos = strpos(strtolower($float_str), 'e')) !== false) {
102  // get either side of the E, e.g. 1.6E+6 => exp E+6, num 1.6
103  $exp = substr($float_str, $pos+1);
104  $num = substr($float_str, 0, $pos);
105 
106  // strip off num sign, if there is one, and leave it off if its + (not required)
107  if ((($num_sign = $num[0]) === '+') || ($num_sign === '-')) {
108  $num = substr($num, 1);
109  } else {
110  $num_sign = '';
111  }
112  if ($num_sign === '+') {
113  $num_sign = '';
114  }
115 
116  // strip off exponential sign ('+' or '-' as in 'E+6') if there is one, otherwise throw error, e.g. E+6 => '+'
117  if ((($exp_sign = $exp[0]) === '+') || ($exp_sign === '-')) {
118  $exp = substr($exp, 1);
119  } else {
120  trigger_error("Could not convert exponential notation to decimal notation: invalid float string '$float_str'", E_USER_ERROR);
121  }
122 
123  // 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
124  $right_dec_places = (($dec_pos = strpos($num, '.')) === false) ? 0 : strlen(substr($num, $dec_pos+1));
125  // 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
126  $left_dec_places = ($dec_pos === false) ? strlen($num) : strlen(substr($num, 0, $dec_pos));
127 
128  // work out number of zeros from exp, exp sign and dec places, e.g. exp 6, exp sign +, dec places 1 => num zeros 5
129  if ($exp_sign === '+') {
130  $num_zeros = $exp - $right_dec_places;
131  } else {
132  $num_zeros = $exp - $left_dec_places;
133  }
134 
135  // build a string with $num_zeros zeros, e.g. '0' 5 times => '00000'
136  $zeros = str_pad('', $num_zeros, '0');
137 
138  // strip decimal from num, e.g. 1.6 => 16
139  if ($dec_pos !== false) {
140  $num = str_replace('.', '', $num);
141  }
142 
143  // if positive exponent, return like 1600000
144  if ($exp_sign === '+') {
145  return $num_sign . $num . $zeros;
146  }
147  // if negative exponent, return like 0.0000016
148  else {
149  return $num_sign . '0.' . $zeros . $num;
150  }
151  }
152  // otherwise, assume already in decimal notation and return
153  else {
154  return $original;
155  }
156  }
157 }
Interface ilMathAdapter.
Add rich text string
comp($left_operand, $right_operand, $scale=null)
Compares two numbers.
equals($left_operand, $right_operand, $scale=null)
{Checks whether or not two numbers are identical.bool}
applyScale($number, $scale=null)
This method adapts the behaviour of bcscale()
normalize($number)
This function fixes problems which occur when locale ist set to de_DE for example, because bc* function expecting strings.
pow($left_operand, $right_operand, $scale=null)
Raises a number to another.
Class ilMathBaseAdapter.
exp2dec($float_str)
Moved from ilMath...
round($value, $precision=0)
string