ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilMathBaseAdapter.php
Go to the documentation of this file.
1<?php
2
23abstract class ilMathBaseAdapter implements ilMathAdapter
24{
28 public function applyScale($left_operand, ?int $scale = null): string
29 {
30 if (is_numeric($left_operand)) {
31 $scale = (int) $scale;
32
33 $left_operand = $this->exp2dec($left_operand);
34 if (strpos($left_operand, '.') === false) {
35 $number_of_decimals = 0;
36 } else {
37 $number_of_decimals = strlen(substr($left_operand, strpos($left_operand, '.') + 1));
38 }
39
40 if ($number_of_decimals > 0 && $number_of_decimals < $scale) {
41 $left_operand = str_pad($left_operand, $scale - $number_of_decimals, '0');
42 } elseif ($number_of_decimals > $scale) {
43 $left_operand = substr($left_operand, 0, -($number_of_decimals - $scale));
44 }
45 }
46
47 return $left_operand;
48 }
49
53 public function round($value, int $precision = 0): string
54 {
55 return number_format($value, $precision, '.', '');
56 }
57
61 public function equals($left_operand, $right_operand, ?int $scale = null): bool
62 {
63 return $this->comp($left_operand, $right_operand, $scale) === 0;
64 }
65
72 protected function normalize($number): ?string
73 {
74 if (null === $number) {
75 return null;
76 }
77
78 $number = trim((string) $number);
79 $number = $this->exp2dec($number);
80 $locale_info = localeconv();
81
82 if ($locale_info['decimal_point'] !== '.') {
83 $append = '';
84 $number_of_decimals = (int) ini_get('precision') - (int) floor(log10(abs($number)));
85 if (0 > $number_of_decimals) {
86 $number *= 10 ** $number_of_decimals;
87 $append = str_repeat('0', -$number_of_decimals);
88 $number_of_decimals = 0;
89 }
90
91 return number_format($number, $number_of_decimals, '.', '') . $append;
92 }
93
94 return $number;
95 }
96
101 protected function exp2dec($float_str): string
102 {
103 // make sure its a standard php float string (i.e. change 0.2e+2 to 20)
104 // php will automatically format floats decimally if they are within a certain range
105 $original = $float_str; // store original float, so we can return a float keeping the pecision when possible
106 $float_str = (string) ((float) ($float_str));
107 $float_str = str_replace(",", ".", $float_str); // convert ',' to '.' (float casting was locale sensitive)
108
109 // if there is an E in the float string
110 if (($pos = stripos($float_str, 'e')) !== false) {
111 // get either side of the E, e.g. 1.6E+6 => exp E+6, num 1.6
112 $exp = substr($float_str, $pos + 1);
113 $num = substr($float_str, 0, $pos);
114
115 // strip off num sign, if there is one, and leave it off if its + (not required)
116 if ((($num_sign = $num[0]) === '+') || ($num_sign === '-')) {
117 $num = substr($num, 1);
118 } else {
119 $num_sign = '';
120 }
121 if ($num_sign === '+') {
122 $num_sign = '';
123 }
124
125 // strip off exponential sign ('+' or '-' as in 'E+6') if there is one, otherwise throw error, e.g. E+6 => '+'
126 if ((($exp_sign = $exp[0]) === '+') || ($exp_sign === '-')) {
127 $exp = substr($exp, 1);
128 } else {
129 throw new DomainException(
130 "Could not convert exponential notation to decimal notation: invalid float string '$float_str'"
131 );
132 }
133
134 // 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
135 $right_dec_places = (($dec_pos = strpos($num, '.')) === false) ? 0 : strlen(substr($num, $dec_pos + 1));
136 // 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
137 $left_dec_places = ($dec_pos === false) ? strlen($num) : strlen(substr($num, 0, $dec_pos));
138
139 // work out number of zeros from exp, exp sign and dec places, e.g. exp 6, exp sign +, dec places 1 => num zeros 5
140 if ($exp_sign === '+') {
141 $num_zeros = $exp - $right_dec_places;
142 } else {
143 $num_zeros = $exp - $left_dec_places;
144 }
145
146 // build a string with $num_zeros zeros, e.g. '0' 5 times => '00000'
147 $zeros = str_pad('', $num_zeros, '0');
148
149 // strip decimal from num, e.g. 1.6 => 16
150 if ($dec_pos !== false) {
151 $num = str_replace('.', '', $num);
152 }
153
154 // if positive exponent, return like 1600000
155 if ($exp_sign === '+') {
156 return $num_sign . $num . $zeros;
157 }
158
159 // if negative exponent, return like 0.0000016
160 return $num_sign . '0.' . $zeros . $num;
161 }
162
163 // otherwise, assume already in decimal notation and return
164 return $original;
165 }
166}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
round($value, int $precision=0)
@inheritDoc
equals($left_operand, $right_operand, ?int $scale=null)
@inheritDoc
applyScale($left_operand, ?int $scale=null)
@inheritDoc
normalize($number)
This function fixes problems which occur when locale ist set to de_DE for example,...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
comp($left_operand, $right_operand, ?int $scale=null)
Compares two numbers.