-
Notifications
You must be signed in to change notification settings - Fork 440
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #115 from frederikbosch/nextrelease
Deal with integer limits, closes #111
- Loading branch information
Showing
12 changed files
with
1,098 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<?php | ||
namespace Money; | ||
|
||
/** | ||
* Calculator Interface | ||
* @author Frederik Bosch | ||
*/ | ||
interface Calculator | ||
{ | ||
|
||
/** | ||
* Returns whether the calculator is supported in | ||
* the current server environment | ||
* | ||
* @return bool | ||
*/ | ||
public static function supported(); | ||
|
||
/** | ||
* Compare a to b | ||
* | ||
* @param int|string $a | ||
* @param int|string $b | ||
* @return int | ||
*/ | ||
public function compare($a, $b); | ||
|
||
/** | ||
* Add added to amount | ||
* | ||
* @param int|string $amount | ||
* @param int|string $addend | ||
* @return int|string | ||
*/ | ||
public function add($amount, $addend); | ||
|
||
/** | ||
* Subtract subtrahend from amount | ||
* @param int|string $amount | ||
* @param int|string $subtrahend | ||
* @return int|string | ||
*/ | ||
public function subtract($amount, $subtrahend); | ||
|
||
/** | ||
* Multiply amount with multiplier | ||
* | ||
* @param int|string $amount | ||
* @param int|float $multiplier | ||
* @return int|string | ||
*/ | ||
public function multiply($amount, $multiplier); | ||
|
||
/** | ||
* Divide amount with divisor | ||
* | ||
* @param int|string $amount | ||
* @param int|float $divisor | ||
* @return int|string | ||
*/ | ||
public function divide($amount, $divisor); | ||
|
||
/** | ||
* Round number to following integer | ||
* | ||
* @param int|string|float $number | ||
* @return int|string | ||
*/ | ||
public function ceil($number); | ||
|
||
/** | ||
* Round number to preceding integer | ||
* | ||
* @param int|string|float $number | ||
* @return int|string | ||
*/ | ||
public function floor($number); | ||
|
||
/** | ||
* Round number, use rounding mode for tie-breaker | ||
* | ||
* @param int|string|float $number | ||
* @param int|string $roundingMode | ||
* @return int|string | ||
*/ | ||
public function round($number, $roundingMode); | ||
|
||
/** | ||
* Share amount among ratio / total portions | ||
* | ||
* @param int|string $amount | ||
* @param int|float $ratio | ||
* @param int|float $total | ||
* @return int|string | ||
*/ | ||
public function share($amount, $ratio, $total); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
<?php | ||
namespace Money\Calculator; | ||
|
||
use Money\Calculator; | ||
use Money\Money; | ||
use Money\Number; | ||
|
||
/** | ||
* Class BcMathCalculator | ||
* @package Money\Calculator | ||
*/ | ||
final class BcMathCalculator implements Calculator | ||
{ | ||
/** | ||
* @var string | ||
*/ | ||
private $scale; | ||
|
||
/** | ||
* @param int $scale | ||
*/ | ||
public function __construct($scale = 14) | ||
{ | ||
$this->scale = $scale; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public static function supported() | ||
{ | ||
return extension_loaded('bcmath'); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function compare($a, $b) | ||
{ | ||
return bccomp($a, $b); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function add($amount, $addend) | ||
{ | ||
return bcadd($amount, $addend); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
* | ||
* @param $amount | ||
* @param $subtrahend | ||
* @return string | ||
*/ | ||
public function subtract($amount, $subtrahend) | ||
{ | ||
return bcsub($amount, $subtrahend); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function multiply($amount, $multiplier) | ||
{ | ||
return bcmul($amount, $multiplier, $this->scale); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function divide($amount, $divisor) | ||
{ | ||
return bcdiv($amount, $divisor, $this->scale); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function ceil($number) | ||
{ | ||
$decimalSeparatorPosition = strpos($number, '.'); | ||
if ($decimalSeparatorPosition === false) { | ||
return $number; | ||
} | ||
|
||
return bcadd($number, '1', 0); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function floor($number) | ||
{ | ||
return bcadd($number, '0', 0); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function round($number, $roundingMode) | ||
{ | ||
$number = new Number($number); | ||
if ($number->isDecimal() === false) { | ||
return (string) $number; | ||
} | ||
|
||
if ($number->isHalf() === false) { | ||
return $this->roundDigit($number); | ||
} | ||
|
||
if ($roundingMode === Money::ROUND_HALF_DOWN) { | ||
return $this->floor((string) $number); | ||
} | ||
|
||
if ($roundingMode === Money::ROUND_HALF_UP) { | ||
return $this->ceil((string) $number); | ||
} | ||
|
||
if ($roundingMode === Money::ROUND_HALF_EVEN) { | ||
if ($number->isCurrentEven() === true) { | ||
return $this->floor((string) $number); | ||
} else { | ||
return $this->ceil((string) $number); | ||
} | ||
} | ||
|
||
if ($roundingMode === Money::ROUND_HALF_ODD) { | ||
if ($number->isCurrentEven() === true) { | ||
return $this->ceil((string) $number); | ||
} else { | ||
return $this->floor((string) $number); | ||
} | ||
} | ||
|
||
throw new \InvalidArgumentException('Unknown rounding mode'); | ||
} | ||
|
||
/** | ||
* @param $number | ||
* @return string | ||
*/ | ||
private function roundDigit(Number $number) | ||
{ | ||
if ($number->isCloserToNext()) { | ||
return $this->ceil((string) $number); | ||
} | ||
|
||
return $this->floor((string) $number); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function share($amount, $ratio, $total) | ||
{ | ||
return $this->floor(bcdiv(bcmul($amount, $ratio, $this->scale), $total, $this->scale)); | ||
} | ||
|
||
} |
Oops, something went wrong.