Overview

Namespaces

  • NGS
    • Client
      • Exception
    • Converter
    • Patterns
  • PHP

Classes

  • BigDecimal
  • BigInt
  • ByteStream
  • LocalDate
  • Location
  • Money
  • Name
  • Point
  • S3
  • Timestamp
  • Utils
  • UUID
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: namespace NGS;
  3: 
  4: require_once(__DIR__.'/Utils.php');
  5: 
  6: use NGS\Utils;
  7: 
  8: /**
  9:  * Used for arbitrary length decimal numbers
 10:  * BigDecimal is a wrapper around primitive string type, and uses bcmath
 11:  * functions for arithmetic operations
 12:  *
 13:  * @property string $value String representation of decimal value
 14:  * @property int $scale Decimal scale (number of decimal places)
 15:  */
 16: class BigDecimal
 17: {
 18:     /** used for new instances, when scale isn't provided */
 19:     const DEFAULT_SCALE = 20;
 20: 
 21:     /** @var string String representation of decimal value */
 22:     protected $value;
 23: 
 24:     /** @var int scale */
 25:     protected $scale;
 26: 
 27:     /**
 28:      * Create a new instance with decimal value and scale
 29:      *
 30:      * @param int|string|float|\NGS\BigDecimal Decimal value or BigDecimal instance
 31:      * @param int $scale Decimal scale (number of decimal places), uses scale from given BigDecimal instance, or uses default scale if null
 32:      */
 33:     public function __construct($value=0, $scale=null)
 34:     {
 35:         if ($value instanceof \NGS\BigDecimal) {
 36:             $this->setScale($scale!==null ? $scale : $value->scale);
 37:             $this->setValue($value->value);
 38:         }
 39:         else {
 40:             $this->setScale($scale!==null ? $scale : self::DEFAULT_SCALE);
 41:             $this->setValue($value);
 42:         }
 43:     }
 44: 
 45:     /**
 46:      * Converts all elements in array to BigDecimal instance
 47:      *
 48:      * @param array $items Input array, each element must be a valid argument for BigDecimal constructor
 49:      * @param bool  $allowNullValues Allow null values in input array
 50:      * @return array Resulting BigDecimal array
 51:      * @throws \InvalidArgumentException If any element is null or invalid type for BigInstance constructor
 52:      */
 53:     public static function toArray(array $items, $allowNullValues=false)
 54:     {
 55:         $results = array();
 56:         try {
 57:             foreach ($items as $key => $val) {
 58:                 if ($allowNullValues && $val===null) {
 59:                     $results[] = null;
 60:                 } elseif ($val === null) {
 61:                     throw new \InvalidArgumentException('Null value found in provided array');
 62:                 } elseif (!$val instanceof \NGS\BigDecimal) {
 63:                     $results[] = new \NGS\BigDecimal($val);
 64:                 } else {
 65:                     $results[] = $val;
 66:                 }
 67:             }
 68:         }
 69:         catch(\Exception $e) {
 70:             throw new \InvalidArgumentException('Element at index '.$key.' could not be converted to BigDecimal!', 42, $e);
 71:         }
 72:         return $results;
 73:     }
 74: 
 75:     /**
 76:      * Converts all elements in array to \NGS\BigDecimal instance
 77:      *
 78:      * @param array $items Source array, each element must be a valid argument for BigDecimal constructor
 79:      * @param int $scale Set non-BigDecimal values to this scale or use default if null
 80:      * @param bool $allowNullValues Allow elements with null value in array
 81:      * @return array BigDecimal Resulting BigDecimal array
 82:      * @throws InvalidArgumentException If any element is null or invalid type for BigInstance constructor
 83:      */
 84:     public static function toArrayWithScale(array $items, $scale, $allowNullValues=false)
 85:     {
 86:         $results = array();
 87:         try {
 88:             foreach ($items as $key => $val) {
 89:                 if ($allowNullValues && $val===null) {
 90:                     $results[] = null;
 91:                 } elseif ($val === null) {
 92:                     throw new InvalidArgumentException('Null value found in provided array');
 93:                 } else {
 94:                     $results[] = new \NGS\BigDecimal($val, $scale);
 95:                 }
 96:             }
 97:         }
 98:         catch(\Exception $e) {
 99:             throw new \InvalidArgumentException('Element at index '.$key.' could not be converted to BigDecimal!', 42, $e);
100:         }
101:         return $results;
102:     }
103: 
104:     public static function round($number, $scale=0)
105:     {
106:         $fix = '5';
107:         for ($i=0;$i<$scale;$i++)
108:             $fix="0{$fix}";
109:         //var_dump($fix);
110:         $number = bcadd($number, "0.$fix", $scale+1);
111:         var_dump($number);
112:         return    bcdiv($number, "1.0",    $scale);
113:     }
114: 
115:     /**
116:      * Sets scale (number of decimal places)
117:      *
118:      * @param int $scale
119:      */
120:     protected function setScale($scale)
121:     {
122:         if (!is_int($scale)) {
123:             throw new \InvalidArgumentException('BigDecimal scale was not int, type was: "'.Utils::getType($scale).'"');
124:         }
125:         elseif ($scale<0) {
126:             throw new \InvalidArgumentException('BigDecimal scale cannot be negative value: "'.Utils::getType($scale).'"');
127:         }
128:         $this->scale = $scale;
129:     }
130: 
131:     /**
132:      * @param string|int|float $value
133:      */
134:     protected function setValue($value)
135:     {
136:         if ($value === null) {
137:             throw new \InvalidArgumentException('BigDecimal value cannot be null');
138:         }
139:         elseif (is_string($value)) {
140:             if (!filter_var($value, FILTER_VALIDATE_INT)
141:                 && !preg_match('/^[-+]?\\d+([.]\\d+)?$/u', $value)) {
142:                 throw new \InvalidArgumentException('Invalid characters in BigDecimal constructor string: '.$value);
143:             }
144:             $this->value = bcadd($value, 0, $this->scale);
145:         }
146:         elseif (is_int($value)) {
147:             $this->value = bcadd($value, 0, $this->scale);
148:         }
149:         elseif (is_float($value)) {
150:             $this->value = bcadd($value, 0, $this->scale);
151:         }
152:         else {
153:             throw new \InvalidArgumentException('Invalid type for BigDecimal value, type was: "'.Utils::getType($value).'"');
154:         }
155:     }
156: 
157:     /**
158:      * Returns string representation of decimal value
159:      *
160:      * @return string
161:      */
162:     public function getValue()
163:     {
164:         return $this->value;
165:     }
166: 
167:     /**
168:      * Returns decimal scale
169:      *
170:      * @return int
171:      */
172:     public function getScale()
173:     {
174:         return $this->scale;
175:     }
176: 
177:     /**
178:      * Magic getter for accessing private value and scale properties
179:      */
180:     public function __get($name)
181:     {
182:         if($name==='value') {
183:             return $this->value;
184:         }
185:         else if($name==='scale') {
186:             return $this->scale;
187:         }
188:         else {
189:             throw new \InvalidArgumentException('Cannot get undefined property "'.$name.'"');
190:         }
191:     }
192: 
193:     /**
194:      * Returns string representation of decimal value
195:      *
196:      * @return string
197:      */
198:     public function __toString()
199:     {
200:         return $this->value;
201:     }
202: 
203:     /**
204:      * Returns string representation of decimal value with given scale
205:      *
206:      * @param int $scale Desired scale (number of decimal places)
207:      * @return string
208:      */
209:     public function toStringWith($scale)
210:     {
211:         return $this->format($scale);
212:     }
213: 
214:     /**
215:      * Returns string representation of decimal value with given scale
216:      *
217:      * @param int $scale Desired scale (number of decimal places)
218:      * @return string
219:      */
220:     public function format($scale)
221:     {
222:         return number_format($this->value, $scale);
223:     }
224: 
225: // ----------------------------------------------------------------------------
226: 
227:     protected function _add(BigDecimal $other)
228:     {
229:         return new BigDecimal(bcadd($this->value, $other->value, $this->scale), $this->scale);
230:     }
231: 
232:     /**
233:      * Adds another BigDecimal value to this instance
234:      *
235:      * @param $other BigDecimal Value to be added
236:      * @return BigDecimal Resulting BigDecimal instance
237:      */
238:     public function add($other)
239:     {
240:         return $this->_add(new BigDecimal($other, $this->scale));
241:     }
242: 
243:     protected function _sub(BigDecimal $other)
244:     {
245:         return new BigDecimal(bcsub($this->value, $other->value, $this->scale), $this->scale);
246:     }
247: 
248:     /**
249:      * Subtract another BigDecimal value from this instance
250:      *
251:      * @param $other BigDecimal Value to be subtracted
252:      * @return BigDecimal Resulting BigDecimal instance
253:      */
254:     public function sub($other)
255:     {
256:         return $this->_sub(new BigDecimal($other, $this->scale));
257:     }
258: 
259: // ----------------------------------------------------------------------------
260: 
261:     protected function _comp(BigDecimal $other)
262:     {
263:         return bccomp($this->value, $other->value, $this->scale);
264:     }
265: 
266:     /**
267:      * Compares with another BigDecimal
268:      *
269:      * @param $other BigDecimal Value to compare with
270:      * @return int Returns 0 if the two values are equal, 1 if other value is
271:      * larger, -1 otherwise.
272:      */
273:     public function comp($other)
274:     {
275:         return $this->_comp(new BigDecimal($other, $this->scale));
276:     }
277: 
278:     protected function _gt(BigDecimal $other)
279:     {
280:         return $this->comp($other) > 0;
281:     }
282: 
283:     /**
284:      * Check if this value is greater than another BigDecimal
285:      *
286:      * @param $other BigDecimal Value to compare with
287:      * @return bool Returns true if greater than other, false otherwise
288:      */
289:     public function gt($other)
290:     {
291:         return $this->_gt(new BigDecimal($other, $this->scale));
292:     }
293: 
294:     protected function _gte(BigDecimal $other) {
295:         return $this->comp($other) >= 0;
296:     }
297: 
298:     /**
299:      * Check if this value is greater or equal than another BigDecimal
300:      *
301:      * @param $other BigDecimal Value to compare with
302:      * @return bool Returns true if greater or equal than other, false otherwise
303:      */
304:     public function gte($other)
305:     {
306:         return $this->_gte(new BigDecimal($other, $this->scale));
307:     }
308: 
309:     protected function _lt(BigDecimal $other)
310:     {
311:         return $this->comp($other) < 0;
312:     }
313: 
314:     /**
315:      * Check if this instance is less than another BigDecimal
316:      *
317:      * @param $other BigDecimal Value to compare with
318:      * @return bool Returns true if less than other, false otherwise
319:      */
320:     public function lt($other)
321:     {
322:         return $this->_lt(new BigDecimal($other, $this->scale));
323:     }
324: 
325:     protected function _lte(BigDecimal $other)
326:     {
327:         return $this->comp($other) <= 0;
328:     }
329: 
330:     /**
331:      * Check if this instance is less or equal than another BigDecimal
332:      *
333:      * @param $other BigDecimal Value to compare with
334:      * @return bool Returns true if less or equal than other, false otherwise
335:      */
336:     public function lte($other)
337:     {
338:         return $this->_lte(new BigDecimal($other, $this->scale));
339:     }
340: 
341: // ----------------------------------------------------------------------------
342: 
343:     protected function _mul(BigDecimal $other)
344:     {
345:         return new BigDecimal(bcmul($this->value, $other->value, $this->scale), $this->scale);
346:     }
347: 
348:     /**
349:      * Multiply with another BigDecimal
350:      *
351:      * @param $other BigDecimal Value to multiply with
352:      * @return BigDecimal Resulting BigDecimal instance
353:      */
354:     public function mul($other)
355:     {
356:         return $this->_mul(new BigDecimal($other, $this->scale));
357:     }
358: 
359:     protected function _div(BigDecimal $other)
360:     {
361:         return new BigDecimal(bcdiv($this->value, $other->value, $this->scale), $this->scale);
362:     }
363: 
364:     /**
365:      * Divide with another BigDecimal
366:      *
367:      * @param $other BigDecimal Value to divide with
368:      * @return BigDecimal Resulting BigDecimal instance
369:      */
370:     public function div($other)
371:     {
372:         return $this->_div(new BigDecimal($other, $this->scale));
373:     }
374: 
375:     protected function _mod(BigDecimal $other)
376:     {
377:         return new BigDecimal(bcmod($this->value, $other->value, $this->scale), $this->scale);
378:     }
379: 
380:     /**
381:      * Get modulus with another BigDecimal
382:      *
383:      * @param $other BigDecimal Value to multiply with
384:      * @return BigDecimal Resulting BigDecimal instance
385:      */
386:     public function mod($other)
387:     {
388:         return $this->_mod(new BigDecimal($other, $this->scale));
389:     }
390: 
391: // ----------------------------------------------------------------------------
392: 
393:     protected function _pow(BigDecimal $other)
394:     {
395:         return new BigDecimal(bcpow($this->value, $other->value, $this->scale));
396:     }
397: 
398:     /**
399:      * Raise this value to another BigDecimal value
400:      *
401:      * @param $other BigDecimal Value to multiply with
402:      * @return BigDecimal Resulting BigDecimal instance
403:      */
404:     public function pow($other)
405:     {
406:         return $this->_pow(self::from($other));
407:     }
408: 
409:     /**
410:      * Square root
411:      *
412:      * @return BigDecimal Resulting BigDecimal instance
413:      */
414:     public function sqrt()
415:     {
416:         return new BigDecimal(bcsqrt($this->value, $this->scale), $this->scale);
417:     }
418: }
419: 
API documentation generated by ApiGen 2.8.0