Skip to content

Commit fce3d88

Browse files
committed
Only require strict check as opt-in
1 parent a9421cd commit fce3d88

File tree

2 files changed

+15
-12
lines changed

2 files changed

+15
-12
lines changed

src/Decimal.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,15 @@ class Decimal implements JsonSerializable, Stringable
6565
/**
6666
* @param object|string|float|int $value
6767
* @param int|null $scale Decimal places in the result. Omit to enable auto-detection.
68+
* @param bool $strict If scale should be strictly checked to avoid accidental precision loss.
6869
*/
69-
public function __construct(object|string|float|int $value, ?int $scale = null)
70+
public function __construct(object|string|float|int $value, ?int $scale = null, bool $strict = false)
7071
{
7172
$value = $this->parseValue($value);
7273
$value = $this->normalizeValue($value);
7374

7475
$this->setValue($value, $scale);
75-
$this->setScale($scale);
76+
$this->setScale($scale, $strict);
7677
}
7778

7879
/**
@@ -146,16 +147,17 @@ protected function normalizeValue(string $value): string
146147
*
147148
* @param object|string|float|int $value
148149
* @param int|null $scale Decimal places in the result. Omit to enable auto-detection.
150+
* @param bool $strict If scale should be strictly checked to avoid accidental precision loss.
149151
*
150152
* @return static
151153
*/
152-
public static function create(object|string|float|int $value, ?int $scale = null): static
154+
public static function create(object|string|float|int $value, ?int $scale = null, bool $strict = false): static
153155
{
154156
if ($scale === null && $value instanceof static) {
155157
return clone $value;
156158
}
157159

158-
return new static($value, $scale);
160+
return new static($value, $scale, $strict);
159161
}
160162

161163
/**
@@ -737,7 +739,7 @@ protected function copy(?string $integerPart = null, ?string $decimalPart = null
737739
}
738740
if ($decimalPart !== null) {
739741
$clone->fractionalPart = $decimalPart;
740-
$clone->setScale(null);
742+
$clone->setScale(null, false);
741743
}
742744
if ($negative !== null) {
743745
$clone->negative = $negative;
@@ -860,15 +862,16 @@ protected function fromScientific(string $value, ?int $scale): void
860862

861863
/**
862864
* @param int|null $scale
865+
* @param bool $strict
863866
*
864867
* @throws \InvalidArgumentException
865868
*
866869
* @return void
867870
*/
868-
protected function setScale(?int $scale): void
871+
protected function setScale(?int $scale, bool $strict): void
869872
{
870873
$calculatedScale = strlen($this->fractionalPart);
871-
if ($scale && $calculatedScale > $scale) {
874+
if ($strict && $scale && $calculatedScale > $scale) {
872875
throw new InvalidArgumentException('Loss of precision detected. Detected scale `' . $calculatedScale . '` > `' . $scale . '` as defined.');
873876
}
874877

tests/DecimalTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,16 +1036,16 @@ public function testDebugInfo(): void
10361036
*/
10371037
public function testPrecisionLossProtection(): void
10381038
{
1039-
$a = Decimal::create('0.1', 50);
1039+
$a = Decimal::create('0.1', 50, true);
10401040
$this->assertSame(50, $a->scale());
10411041

1042-
$b = Decimal::create($a);
1042+
$b = Decimal::create($a, null, true);
10431043
$this->assertSame(50, $b->scale());
10441044

1045-
$c = Decimal::create($b, 6); // Not 50 if manually overwritten
1045+
$c = Decimal::create($b, 6, true); // Not 50 if manually overwritten
10461046
$this->assertSame(6, $c->scale());
10471047

1048-
$d = Decimal::create($c, 64);
1048+
$d = Decimal::create($c, 64, true);
10491049
$this->assertSame(64, $d->scale());
10501050
}
10511051

@@ -1057,6 +1057,6 @@ public function testPrecisionLossFail(): void
10571057
$this->expectException(InvalidArgumentException::class);
10581058
$this->expectExceptionMessage('Loss of precision detected');
10591059

1060-
Decimal::create('0.123', 2);
1060+
Decimal::create('0.123', 2, true);
10611061
}
10621062
}

0 commit comments

Comments
 (0)