Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 2.7.1 under development

- no changes in this release.
- New #156: Add `NumericHelper::trimDecimalZeros()` (@samdark)

## 2.7.0 November 23, 2025

Expand Down
38 changes: 37 additions & 1 deletion src/NumericHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@
}

/**
* Converts human readable size to bytes.
* Converts human-readable size to bytes.
*
* @param string $string Human readable size. Examples: `1024`, `1kB`, `1.5M`, `1GiB`. Full
* list of supported postfixes in {@see FILESYSTEM_SIZE_POSTFIXES}.
Expand Down Expand Up @@ -157,9 +157,45 @@
throw new InvalidArgumentException("Not supported postfix '$postfix' in input string: $string");
}

return (int) ((float) $numericPart * $postfixMultiplier);

Check warning on line 160 in src/NumericHelper.php

View workflow job for this annotation

GitHub Actions / mutation / PHP 8.5-ubuntu-latest

Escaped Mutant for Mutator "CastFloat": @@ @@ if ($postfixMultiplier === null) { throw new InvalidArgumentException("Not supported postfix '{$postfix}' in input string: {$string}"); } - return (int) ((float) $numericPart * $postfixMultiplier); + return (int) ($numericPart * $postfixMultiplier); } throw new InvalidArgumentException("Incorrect input string: {$string}"); }
}

throw new InvalidArgumentException("Incorrect input string: $string");
}

/**
* Trims trailing decimal zeros from a numeric-like string.
*
* If the fractional part consists only of zeros, the decimal separator is removed as well.
* The value that is `null` or empty is returned as-is.
*
* @param string|null $value String representation of a number or any string potentially
* containing a decimal part.
*
* @return string|null The input string with trailing decimal zeros (and a trailing decimal
* separator, if any) removed, or `null` if the input was `null` or an empty string.
*/
public static function trimDecimalZeros(?string $value): ?string
{
if ($value === null) {
return null;
}

$value = trim($value);
if ($value === '') {
return null;
}

if (!str_contains($value, '.')) {
return $value;
}
/** @psalm-suppress PossiblyNullArgument */
$value = rtrim($value, '0');

if ($value === '' || !str_ends_with($value, '.')) {
return $value;
}

return substr($value, 0, -1);
}
}
22 changes: 22 additions & 0 deletions tests/NumericHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,26 @@ public function testConvertHumanReadableSizeToBytesWithInvalidStrings(string $st
$this->expectExceptionObject(new \InvalidArgumentException($message));
NumericHelper::convertHumanReadableSizeToBytes($string);
}

public static function dataTrimDecimalZeros(): array
{
return [
'no decimals in integer with zeros' => ['390', '390'],
'all zeros' => ['390.000', '390'],
'no zeros' => ['3.14', '3.14'],
'some zeros' => ['42.010', '42.01'],
'null' => [null, null],
'zeros' => ['0.0', '0'],
'empty' => ['', null],
'decimal only' => ['.5', '.5'],
'start with zero' => ['0.25', '0.25'],
'negative' => ['-3.000', '-3'],
];
}

#[DataProvider('dataTrimDecimalZeros')]
public function testTrimDecimalZeros(?string $input, ?string $expected): void
{
$this->assertSame($expected, NumericHelper::trimDecimalZeros($input));
}
}
12 changes: 12 additions & 0 deletions tests/benchmarks/NumericHelperBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,16 @@ public function benchNormalize(): void
NumericHelper::normalize('1,000,000.123');
NumericHelper::normalize('1 000 000,123');
}

public function benchTrimDecimalZeros(): void
{
NumericHelper::trimDecimalZeros('390');
NumericHelper::trimDecimalZeros('390.000');
NumericHelper::trimDecimalZeros('3.14');
NumericHelper::trimDecimalZeros('42.010');
NumericHelper::trimDecimalZeros('0.0');
NumericHelper::trimDecimalZeros('.5');
NumericHelper::trimDecimalZeros('0.25');
NumericHelper::trimDecimalZeros('-3.000');
}
}
Loading