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

Commit 4ebb197

Browse files
author
Andreu Correa
committed
Add regression test & simplify code
1 parent 21a74f5 commit 4ebb197

File tree

3 files changed

+54
-55
lines changed

3 files changed

+54
-55
lines changed

src/Decimal.php

Lines changed: 21 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,16 @@ private function __clone()
4848
*
4949
* @param mixed $value
5050
* @param int $scale
51-
* @param bool $removeZeros If true then removes trailing zeros from the number representation
5251
* @return Decimal
5352
*/
54-
public static function create($value, int $scale = null, bool $removeZeros = false): Decimal
53+
public static function create($value, int $scale = null): Decimal
5554
{
5655
if (\is_int($value)) {
5756
return self::fromInteger($value);
5857
} elseif (\is_float($value)) {
59-
return self::fromFloat($value, $scale, $removeZeros);
58+
return self::fromFloat($value, $scale);
6059
} elseif (\is_string($value)) {
61-
return self::fromString($value, $scale, $removeZeros);
60+
return self::fromString($value, $scale);
6261
} elseif ($value instanceof Decimal) {
6362
return self::fromDecimal($value, $scale);
6463
} else {
@@ -79,10 +78,9 @@ public static function fromInteger(int $intValue): Decimal
7978
/**
8079
* @param float $fltValue
8180
* @param int $scale
82-
* @param bool $removeZeros If true then removes trailing zeros from the number representation
8381
* @return Decimal
8482
*/
85-
public static function fromFloat(float $fltValue, int $scale = null, bool $removeZeros = false): Decimal
83+
public static function fromFloat(float $fltValue, int $scale = null): Decimal
8684
{
8785
self::paramsValidation($fltValue, $scale);
8886

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

95-
$defaultScale = self::DEFAULT_SCALE;
96-
9793
$strValue = (string) $fltValue;
9894
if (\preg_match(self::EXP_NUM_GROUPS_NUMBER_REGEXP, $strValue, $capture)) {
9995
if (null === $scale) {
10096
$scale = ('-' === $capture['sign'])
10197
? $capture['exp'] + \strlen($capture['dec'])
102-
: $defaultScale;
98+
: self::DEFAULT_SCALE;
10399
}
104100
$strValue = \number_format($fltValue, $scale, '.', '');
105-
}
106-
107-
if (null === $scale) {
108-
$scale = $defaultScale;
109-
}
101+
} else {
102+
$naturalScale = \strlen((string)fmod($fltValue, 1.0)) - 2 - (($fltValue < 0) ? 1 : 0);
110103

111-
if ($removeZeros) {
112-
$strValue = self::removeTrailingZeros($strValue, $scale);
104+
if (null === $scale) {
105+
$scale = $naturalScale;
106+
} else {
107+
$strValue .= str_pad('', $scale - $naturalScale, '0');
108+
}
113109
}
114110

115111
return new static($strValue, $scale);
@@ -118,10 +114,9 @@ public static function fromFloat(float $fltValue, int $scale = null, bool $remov
118114
/**
119115
* @param string $strValue
120116
* @param integer $scale
121-
* @param boolean $removeZeros If true then removes trailing zeros from the number representation
122117
* @return Decimal
123118
*/
124-
public static function fromString(string $strValue, int $scale = null, bool $removeZeros = false): Decimal
119+
public static function fromString(string $strValue, int $scale = null): Decimal
125120
{
126121
self::paramsValidation($strValue, $scale);
127122

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

147-
$scale = (null !== $scale) ? $scale : $min_scale;
142+
$scale = $scale ?? $min_scale;
148143
if ($scale < $min_scale) {
149144
$value = self::innerRound($value, $scale);
150145
}
151-
if ($removeZeros) {
152-
$value = self::removeTrailingZeros($value, $scale);
153-
}
154146

155147
return new static($value, $scale);
156148
}
@@ -312,28 +304,25 @@ public function pow(Decimal $b, int $scale = null): Decimal
312304
if ($b->isPositive()) {
313305
return Decimal::fromDecimal($this, $scale);
314306
} else {
315-
throw new \DomainException(
316-
"zero can't be powered to zero or negative numbers."
317-
);
307+
throw new \DomainException("zero can't be powered to zero or negative numbers.");
318308
}
319309
} elseif ($b->isZero()) {
320310
return DecimalConstants::One();
321311
} else if ($b->isNegative()) {
322312
return DecimalConstants::One()->div(
323-
$this->pow($b->additiveInverse()), $scale
313+
$this->pow($b->additiveInverse(), max($scale, self::DEFAULT_SCALE)),
314+
max($scale, self::DEFAULT_SCALE)
324315
);
325-
} elseif ($b->scale === 0) {
326-
$pow_scale = $scale === null ?
327-
\max($this->scale, $b->scale) : \max($this->scale, $b->scale, $scale);
316+
} elseif (0 === $b->scale) {
317+
$pow_scale = \max($this->scale, $b->scale, $scale ?? 0);
328318

329319
return self::fromString(
330320
\bcpow($this->value, $b->value, $pow_scale+1),
331321
$pow_scale
332322
);
333323
} else {
334324
if ($this->isPositive()) {
335-
$pow_scale = $scale === null ?
336-
\max($this->scale, $b->scale) : \max($this->scale, $b->scale, $scale);
325+
$pow_scale = \max($this->scale, $b->scale, $scale ?? 0);
337326

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

1302-
private static function removeTrailingZeros(string $strValue, int &$scale): string
1303-
{
1304-
\preg_match('/^[+\-]?[0-9]+(\.([0-9]*[1-9])?(0+)?)?$/', $strValue, $captures);
1305-
1306-
if (\count($captures) === 4) {
1307-
$toRemove = \strlen($captures[3]);
1308-
$scale = \strlen($captures[2]);
1309-
$strValue = \substr(
1310-
$strValue,
1311-
0,
1312-
\strlen($strValue) - $toRemove - (0 === $scale ? 1 : 0)
1313-
);
1314-
}
1315-
1316-
return $strValue;
1317-
}
1318-
13191291
/**
1320-
* Counts the number of significative digits of $val.
1292+
* Counts the number of significant digits of $val.
13211293
* Assumes a consistent internal state (without zeros at the end or the start).
13221294
*
13231295
* @param Decimal $val

tests/Decimal/DecimalFromFloatTest.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22
declare(strict_types=1);
33

44
use Litipk\BigNumbers\Decimal as Decimal;
5-
use Litipk\Exceptions\InvalidArgumentTypeException as InvalidArgumentTypeException;
65
use PHPUnit\Framework\TestCase;
76

8-
date_default_timezone_set('UTC');
9-
107
class DecimalFromFloatTest extends TestCase
118
{
129
/**
@@ -27,7 +24,6 @@ public function floatProvider()
2724
[-1.1234567890, "-1.123456789"],
2825
[0.000001, "0.0000010"],
2926
[0.000001, "0.00", 2],
30-
[0.000001, "0.000001", null, !!'removeZeroes'],
3127
[90.05, "90.05"],
3228
];
3329

@@ -61,9 +57,9 @@ public function floatProvider()
6157
/**
6258
* @dataProvider floatProvider
6359
*/
64-
public function testFromFloat($in, $str, $scale=null, $removeZeroes=false)
60+
public function testFromFloat(float $in, string $str, int $scale = null)
6561
{
66-
$v = Decimal::fromFloat($in, $scale, $removeZeroes);
62+
$v = Decimal::fromFloat($in, $scale);
6763
$this->assertSame($str, $v->innerValue());
6864
}
6965
}

tests/regression/issue53Test.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Litipk\BigNumbers\Decimal;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class issue53Test extends TestCase
9+
{
10+
public function test_that_no_division_by_zero_is_performed_without_explicit_scale()
11+
{
12+
$d1 = Decimal::create(192078120.5);
13+
$d2 = Decimal::create(31449600);
14+
15+
$d1->div($d2);
16+
17+
// We are asserting that no exception is thrown
18+
$this->assertTrue(true);
19+
}
20+
21+
public function test_that_no_division_by_zero_is_performed_with_explicit_scale()
22+
{
23+
$d1 = Decimal::create(192078120.5, 28);
24+
$d2 = Decimal::create(31449600, 28);
25+
26+
$d1->div($d2);
27+
28+
// We are asserting that no exception is thrown
29+
$this->assertTrue(true);
30+
}
31+
}

0 commit comments

Comments
 (0)