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
4require_once 'Services/Math/interfaces/interface.ilMathAdapter.php';
5
10abstract 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}
An exception for terminatinating execution or to throw for unit testing.
Class ilMathBaseAdapter.
exp2dec($float_str)
Moved from ilMath... Converts numbers in the form "1.5e4" into decimal notation.
round($value, $precision=0)
string
applyScale($number, $scale=null)
This method adapts the behaviour of bcscale()
equals($left_operand, $right_operand, $scale=null)
{Checks whether or not two numbers are identical.bool}
normalize($number)
This function fixes problems which occur when locale ist set to de_DE for example,...
Interface ilMathAdapter.
pow($left_operand, $right_operand, $scale=null)
Raises a number to another.
comp($left_operand, $right_operand, $scale=null)
Compares two numbers.