ext-decimal icon indicating copy to clipboard operation
ext-decimal copied to clipboard

TypeError: Decimal\Decimal::add() expected parameter 1 to be a string, integer, or decimal

Open thefantas opened this issue 4 years ago • 2 comments

Why Decimal does not accept float? It is a nuisance to make use of strval() or (string) in addition to checking that it is not NULL or empty.

use Decimal\Decimal;
class ModDecimal {
  public $decimal;
  function __construct($val = '') {
	  $var = strval(empty(trim($val))?'0':trim($val));
      $this->decimal = new Decimal($var);
  }
  function get_decimal() {
    return $this->decimal;
  }
}

$ok = (new ModDecimal(" 5.05"))->get_decimal()->add(20);
print_r($ok);

Decimal\Decimal Object ( [value] => 25.05 [precision] => 28 )

thefantas avatar Jan 18 '21 00:01 thefantas

Given that this is a library for accurate decimal arithmetic and floats use inaccurate decimal representations (eg. 0.1), the decision to disallow float was to encourage an avoidance of float entirely. If a float is on hand, such as one returned by another library or legacy component, the responsibility to convert to string is placed on the caller as an explicit decision.

Could you please share some examples where you find it a nuisance? I am open to relaxing this.

rtheunissen avatar Jan 19 '21 01:01 rtheunissen

<?php
use Decimal\Decimal;

use Decimal\Decimal;

class ModDecimal {
	public $decimal;
	function __construct($val = '') {
		$this->decimal = new Decimal($this->filter($val));
	}
	function __call($name, $arguments) {
		$args2;
		if (in_array($name, ['add','sub']) && empty($arguments))
			$arguments = array(0);
		else if (in_array($name, ['mul','div']) && empty($arguments))
			$arguments = array(1);
		foreach($arguments as $args)
			$args2[] = $this->filter($args);
		if (empty($args2))
			$run_decimal = $this->decimal->$name();
		else
			$run_decimal = $this->decimal->$name(...$args2);
		if (in_array($name, ['toFixed','toInt','toFloat','toString']))
			return $run_decimal;
		else
			return new ModDecimal($run_decimal);
	}
	function filter($val = '') {
		if (is_object($val) && get_class($val)=='ModDecimal')
			return $val->decimal;
		else if (is_object($val) && get_class($val)=='Decimal\Decimal')
			return $val;
		return strval(empty(trim($val))?'0':trim($val));
	}
	function get_decimal() {
		return $this->decimal;
	}
	// operator - The operator. Valid options are ==, <=, <, >=, >, <>, eq, lt, lte, gt, gte, ne
	function Mcompare($val = '', $operator='==') {
		$val = $this->filter($val);
		switch ($operator) {
			// equal
			case "==":
			case "eq": {
				if ($this->decimal->compareTo($val)==0) {
					return true;
				}
				break;
			}
			// less than
			case "<":
			case "lt": {
				if ($this->decimal->compareTo($val)==-1) {
					return true;
				}
				break;	
			}
			// less than or equal
			case "<=":
			case "lte": {
				if ($this->Mcompare($val, '<') || $this->Mcompare($val, '==')) {
					return true;
				}
				break;
			}
			// greater than
			case ">":
			case "gt": {
				if ($this->decimal->compareTo($val)==1) {
					return true;
				}
				break;	
			}
			// greater than or equal
			case ">=":
			case "gte": {
				if ($this->Mcompare($val, '>') || $this->Mcompare($val, '==')) {
					return true;
				}
				break;	
			}
			case "<>":
			case "!=":
			case "ne": {
				if ($this->decimal->compareTo($val)!=0) {
					return true;
				}
				break;	
			}
			default: {
				die("Operador desconccido '".$operator."' en Mcompare()");	
			}
		}
		return false;
	}
}
$data1=0.00054;
$data2="    2";
echo (New Decimal((string)$data1))->mul((string)trim($data2))->toString();
echo (New ModDecimal($data1))->add($data2)->toString(); 

With this I no longer have to worry about whether the data is NULL, float or has spaces.

thefantas avatar Jan 19 '21 14:01 thefantas