From dd5b45ae9648f8142aaab7d5b295552de6d646aa Mon Sep 17 00:00:00 2001 From: Jens Scherbl Date: Fri, 9 Aug 2024 11:29:23 +0200 Subject: [PATCH] Adds `Number` class as thin wrapper for `BCMath` --- composer.json | 1 + src/Number.php | 144 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 src/Number.php diff --git a/composer.json b/composer.json index 5a83d4a..d3a2902 100644 --- a/composer.json +++ b/composer.json @@ -47,6 +47,7 @@ "require": { "php": "^8.3", + "ext-bcmath": "*", "brick/math": "^0.12" }, "require-dev": diff --git a/src/Number.php b/src/Number.php new file mode 100644 index 0000000..1db84e9 --- /dev/null +++ b/src/Number.php @@ -0,0 +1,144 @@ +value = $this->parse(value: $value); + } + + private function parse(self|string|int $value): string + { + if ($value instanceof self) { + return $value->__toString(); + } else { + $parsed = strval(value: $value); + + if (!preg_match( + pattern: '/^[+-]?[0-9]*(\.[0-9]*)?$/', + subject: $parsed + )) { + throw new InvalidArgumentException( + message: 'Invalid number.' + ); + } + return $parsed; + } + } + + public function __toString(): string + { + return $this->value; + } + + public function plus(self|string|int $value): self + { + $value = $this->parse(value: $value); + $result = bcadd(num1: $this->value, num2: $value, scale: self::SCALE); + + return new self(value: $result); + } + + public function minus(self|string|int $value): self + { + $value = $this->parse(value: $value); + $result = bcsub(num1: $this->value, num2: $value, scale: self::SCALE); + + return new self(value: $result); + } + + public function multipliedBy(self|string|int $value): self + { + $value = $this->parse(value: $value); + $result = bcmul(num1: $this->value, num2: $value, scale: self::SCALE); + + return new self(value: $result); + } + + public function dividedBy(self|string|int $value): self + { + $value = $this->parse(value: $value); + $result = bcdiv(num1: $this->value, num2: $value, scale: self::SCALE); + + return new self(value: $result); + } + + public function abs(): self + { + $isNegative = $this->isNegative(); + + if ($isNegative) { + $result = bcmul(num1: $this->value, num2: '-1', scale: self::SCALE); + + return new self(value: $result); + } + return $this; + } + + public function isZero(): bool + { + $result = bccomp(num1: $this->value, num2: '0', scale: self::SCALE); + + return $result === 0; + } + + public function isPositive(): bool + { + $result = bccomp(num1: $this->value, num2: '0', scale: self::SCALE); + + return $result === 1; + } + + public function isNegative(): bool + { + $result = bccomp(num1: $this->value, num2: '0', scale: self::SCALE); + + return $result === -1; + } + + public function isGreaterThan(self|string|int $value): bool + { + $value = $this->parse(value: $value); + $result = bccomp(num1: $this->value, num2: $value, scale: self::SCALE); + + return $result === 1; + } + + public function isLessThan(self|string|int $value): bool + { + $value = $this->parse(value: $value); + $result = bccomp(num1: $this->value, num2: $value, scale: self::SCALE); + + return $result === -1; + } + + public function round(int $scale): string + { + $number = floatval(value: $this->value); + + return number_format(num: $number, decimals: $scale, thousands_separator: ''); + } +}