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

Commit 4b93585

Browse files
author
Andreu Correa Casablanca
committed
Extract fromExpoNotationString method
1 parent 348b6b9 commit 4b93585

File tree

1 file changed

+48
-21
lines changed

1 file changed

+48
-21
lines changed

src/Decimal.php

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
*/
1717
class Decimal
1818
{
19+
const CLASSIC_DECIMAL_NUMBER_REGEXP = '/^([+\-]?)0*(([1-9][0-9]*|[0-9])(\.[0-9]+)?)$/';
20+
const EXP_NOTATION_NUMBER_REGEXP = '/([+\-]?)0*([0-9](\.[0-9]+)?)[eE]([+\-]?)(\d+)/';
21+
const EXP_NUM_GROUPS_NUMBER_REGEXP = "/^ (?P<int> \d*) (?: \. (?P<dec> \d+) ) E (?P<sign>[\+\-]) (?P<exp>\d+) $/x";
22+
1923
/**
2024
* Internal numeric value
2125
* @var string
@@ -90,7 +94,7 @@ public static function fromFloat(float $fltValue, int $scale = null, bool $remov
9094
$defaultScale = 16;
9195

9296
$strValue = (string) $fltValue;
93-
if (\preg_match("/^ (?P<int> \d*) (?: \. (?P<dec> \d+) ) E (?P<sign>[\+\-]) (?P<exp>\d+) $/x", $strValue, $capture)) {
97+
if (\preg_match(self::EXP_NUM_GROUPS_NUMBER_REGEXP, $strValue, $capture)) {
9498
if ($scale === null) {
9599
if ($capture['sign'] == '-') {
96100
$scale = $capture['exp'] + \strlen($capture['dec']);
@@ -122,37 +126,26 @@ public static function fromString(string $strValue, int $scale = null, bool $rem
122126
{
123127
self::paramsValidation($strValue, $scale);
124128

125-
if (\preg_match('/^([+\-]?)0*(([1-9][0-9]*|[0-9])(\.[0-9]+)?)$/', $strValue, $captures) === 1) {
129+
if (\preg_match(self::CLASSIC_DECIMAL_NUMBER_REGEXP, $strValue, $captures) === 1) {
126130

127131
// Now it's time to strip leading zeros in order to normalize inner values
128132
$value = self::normalizeSign($captures[1]) . $captures[2];
129133
$min_scale = isset($captures[4]) ? \max(0, \strlen($captures[4]) - 1) : 0;
130134

131-
} elseif (\preg_match('/([+\-]?)0*([0-9](\.[0-9]+)?)[eE]([+\-]?)(\d+)/', $strValue, $captures) === 1) {
132-
133-
$mantissa_scale = \max(\strlen($captures[3]) - 1, 0);
134-
135-
$exp_val = (int)$captures[5];
136-
137-
if (self::normalizeSign($captures[4]) === '') {
138-
$min_scale = \max($mantissa_scale - $exp_val, 0);
139-
$tmp_multiplier = \bcpow('10', (string)$exp_val);
140-
} else {
141-
$min_scale = $mantissa_scale + $exp_val;
142-
$tmp_multiplier = \bcpow('10', (string)-$exp_val, $exp_val);
143-
}
144-
145-
$value = self::normalizeSign($captures[1]) . \bcmul(
135+
} elseif (\preg_match(self::EXP_NOTATION_NUMBER_REGEXP, $strValue, $captures) === 1) {
136+
list($min_scale, $value) = self::fromExpNotationString(
137+
$scale,
138+
$captures[1],
146139
$captures[2],
147-
$tmp_multiplier,
148-
\max($min_scale, $scale !== null ? $scale : 0)
140+
$captures[3],
141+
$captures[4],
142+
(int)$captures[5]
149143
);
150-
151144
} else {
152145
throw new NaNInputError('strValue must be a number');
153146
}
154147

155-
$scale = ($scale!==null) ? $scale : $min_scale;
148+
$scale = (null !== $scale) ? $scale : $min_scale;
156149
if ($scale < $min_scale) {
157150
$value = self::innerRound($value, $scale);
158151
}
@@ -1092,6 +1085,40 @@ public function __toString(): string
10921085
return $this->value;
10931086
}
10941087

1088+
/*
1089+
*
1090+
*/
1091+
private static function fromExpNotationString(
1092+
int $scale = null,
1093+
string $sign,
1094+
string $mantissa,
1095+
string $mantissaDecimals,
1096+
string $expSign,
1097+
int $expVal
1098+
): array
1099+
{
1100+
$mantissaScale = \max(\strlen($mantissaDecimals) - 1, 0);
1101+
1102+
if (self::normalizeSign($expSign) === '') {
1103+
$minScale = \max($mantissaScale - $expVal, 0);
1104+
$tmp_multiplier = \bcpow('10', (string)$expVal);
1105+
} else {
1106+
$minScale = $mantissaScale + $expVal;
1107+
$tmp_multiplier = \bcpow('10', (string)-$expVal, $expVal);
1108+
}
1109+
1110+
$value = (
1111+
self::normalizeSign($sign) .
1112+
\bcmul(
1113+
$mantissa,
1114+
$tmp_multiplier,
1115+
\max($minScale, $scale ?? 0)
1116+
)
1117+
);
1118+
1119+
return [$minScale, $value];
1120+
}
1121+
10951122
/**
10961123
* "Rounds" the decimal string to have at most $scale digits after the point
10971124
*

0 commit comments

Comments
 (0)