Skip to content
This repository has been archived by the owner on Dec 27, 2023. It is now read-only.

Commit

Permalink
Add regression test & simplify code
Browse files Browse the repository at this point in the history
  • Loading branch information
Andreu Correa committed Apr 30, 2017
1 parent 21a74f5 commit 4ebb197
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 55 deletions.
70 changes: 21 additions & 49 deletions src/Decimal.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,16 @@ private function __clone()
*
* @param mixed $value
* @param int $scale
* @param bool $removeZeros If true then removes trailing zeros from the number representation
* @return Decimal
*/
public static function create($value, int $scale = null, bool $removeZeros = false): Decimal
public static function create($value, int $scale = null): Decimal
{
if (\is_int($value)) {
return self::fromInteger($value);
} elseif (\is_float($value)) {
return self::fromFloat($value, $scale, $removeZeros);
return self::fromFloat($value, $scale);
} elseif (\is_string($value)) {
return self::fromString($value, $scale, $removeZeros);
return self::fromString($value, $scale);
} elseif ($value instanceof Decimal) {
return self::fromDecimal($value, $scale);
} else {
Expand All @@ -79,10 +78,9 @@ public static function fromInteger(int $intValue): Decimal
/**
* @param float $fltValue
* @param int $scale
* @param bool $removeZeros If true then removes trailing zeros from the number representation
* @return Decimal
*/
public static function fromFloat(float $fltValue, int $scale = null, bool $removeZeros = false): Decimal
public static function fromFloat(float $fltValue, int $scale = null): Decimal
{
self::paramsValidation($fltValue, $scale);

Expand All @@ -92,24 +90,22 @@ public static function fromFloat(float $fltValue, int $scale = null, bool $remov
throw new NaNInputError("fltValue can't be NaN");
}

$defaultScale = self::DEFAULT_SCALE;

$strValue = (string) $fltValue;
if (\preg_match(self::EXP_NUM_GROUPS_NUMBER_REGEXP, $strValue, $capture)) {
if (null === $scale) {
$scale = ('-' === $capture['sign'])
? $capture['exp'] + \strlen($capture['dec'])
: $defaultScale;
: self::DEFAULT_SCALE;
}
$strValue = \number_format($fltValue, $scale, '.', '');
}

if (null === $scale) {
$scale = $defaultScale;
}
} else {
$naturalScale = \strlen((string)fmod($fltValue, 1.0)) - 2 - (($fltValue < 0) ? 1 : 0);

if ($removeZeros) {
$strValue = self::removeTrailingZeros($strValue, $scale);
if (null === $scale) {
$scale = $naturalScale;
} else {
$strValue .= str_pad('', $scale - $naturalScale, '0');
}
}

return new static($strValue, $scale);
Expand All @@ -118,10 +114,9 @@ public static function fromFloat(float $fltValue, int $scale = null, bool $remov
/**
* @param string $strValue
* @param integer $scale
* @param boolean $removeZeros If true then removes trailing zeros from the number representation
* @return Decimal
*/
public static function fromString(string $strValue, int $scale = null, bool $removeZeros = false): Decimal
public static function fromString(string $strValue, int $scale = null): Decimal
{
self::paramsValidation($strValue, $scale);

Expand All @@ -144,13 +139,10 @@ public static function fromString(string $strValue, int $scale = null, bool $rem
throw new NaNInputError('strValue must be a number');
}

$scale = (null !== $scale) ? $scale : $min_scale;
$scale = $scale ?? $min_scale;
if ($scale < $min_scale) {
$value = self::innerRound($value, $scale);
}
if ($removeZeros) {
$value = self::removeTrailingZeros($value, $scale);
}

return new static($value, $scale);
}
Expand Down Expand Up @@ -312,28 +304,25 @@ public function pow(Decimal $b, int $scale = null): Decimal
if ($b->isPositive()) {
return Decimal::fromDecimal($this, $scale);
} else {
throw new \DomainException(
"zero can't be powered to zero or negative numbers."
);
throw new \DomainException("zero can't be powered to zero or negative numbers.");
}
} elseif ($b->isZero()) {
return DecimalConstants::One();
} else if ($b->isNegative()) {
return DecimalConstants::One()->div(
$this->pow($b->additiveInverse()), $scale
$this->pow($b->additiveInverse(), max($scale, self::DEFAULT_SCALE)),
max($scale, self::DEFAULT_SCALE)
);
} elseif ($b->scale === 0) {
$pow_scale = $scale === null ?
\max($this->scale, $b->scale) : \max($this->scale, $b->scale, $scale);
} elseif (0 === $b->scale) {
$pow_scale = \max($this->scale, $b->scale, $scale ?? 0);

return self::fromString(
\bcpow($this->value, $b->value, $pow_scale+1),
$pow_scale
);
} else {
if ($this->isPositive()) {
$pow_scale = $scale === null ?
\max($this->scale, $b->scale) : \max($this->scale, $b->scale, $scale);
$pow_scale = \max($this->scale, $b->scale, $scale ?? 0);

$truncated_b = \bcadd($b->value, '0', 0);
$remaining_b = \bcsub($b->value, $truncated_b, $b->scale);
Expand Down Expand Up @@ -1299,25 +1288,8 @@ private static function normalizeSign(string $sign): string
return $sign;
}

private static function removeTrailingZeros(string $strValue, int &$scale): string
{
\preg_match('/^[+\-]?[0-9]+(\.([0-9]*[1-9])?(0+)?)?$/', $strValue, $captures);

if (\count($captures) === 4) {
$toRemove = \strlen($captures[3]);
$scale = \strlen($captures[2]);
$strValue = \substr(
$strValue,
0,
\strlen($strValue) - $toRemove - (0 === $scale ? 1 : 0)
);
}

return $strValue;
}

/**
* Counts the number of significative digits of $val.
* Counts the number of significant digits of $val.
* Assumes a consistent internal state (without zeros at the end or the start).
*
* @param Decimal $val
Expand Down
8 changes: 2 additions & 6 deletions tests/Decimal/DecimalFromFloatTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
declare(strict_types=1);

use Litipk\BigNumbers\Decimal as Decimal;
use Litipk\Exceptions\InvalidArgumentTypeException as InvalidArgumentTypeException;
use PHPUnit\Framework\TestCase;

date_default_timezone_set('UTC');

class DecimalFromFloatTest extends TestCase
{
/**
Expand All @@ -27,7 +24,6 @@ public function floatProvider()
[-1.1234567890, "-1.123456789"],
[0.000001, "0.0000010"],
[0.000001, "0.00", 2],
[0.000001, "0.000001", null, !!'removeZeroes'],
[90.05, "90.05"],
];

Expand Down Expand Up @@ -61,9 +57,9 @@ public function floatProvider()
/**
* @dataProvider floatProvider
*/
public function testFromFloat($in, $str, $scale=null, $removeZeroes=false)
public function testFromFloat(float $in, string $str, int $scale = null)
{
$v = Decimal::fromFloat($in, $scale, $removeZeroes);
$v = Decimal::fromFloat($in, $scale);
$this->assertSame($str, $v->innerValue());
}
}
31 changes: 31 additions & 0 deletions tests/regression/issue53Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

use Litipk\BigNumbers\Decimal;
use PHPUnit\Framework\TestCase;

class issue53Test extends TestCase
{
public function test_that_no_division_by_zero_is_performed_without_explicit_scale()
{
$d1 = Decimal::create(192078120.5);
$d2 = Decimal::create(31449600);

$d1->div($d2);

// We are asserting that no exception is thrown
$this->assertTrue(true);
}

public function test_that_no_division_by_zero_is_performed_with_explicit_scale()
{
$d1 = Decimal::create(192078120.5, 28);
$d2 = Decimal::create(31449600, 28);

$d1->div($d2);

// We are asserting that no exception is thrown
$this->assertTrue(true);
}
}

0 comments on commit 4ebb197

Please sign in to comment.