Skip to content

Commit

Permalink
Merge pull request #13 from sirn-se/v2.4
Browse files Browse the repository at this point in the history
V2.4 multipleOf rounding methods
  • Loading branch information
sirn-se authored Aug 4, 2024
2 parents 598f301 + 3aec98f commit 8a6ad05
Show file tree
Hide file tree
Showing 15 changed files with 382 additions and 49 deletions.
18 changes: 9 additions & 9 deletions .github/workflows/acceptance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ jobs:
test:
strategy:
matrix:
php-versions: ["7.4", "8.0", "8.1", "8.2", "8.3", "8.4"]
php-versions: ["8.0", "8.1", "8.2", "8.3", "8.4"]
runs-on: ubuntu-latest
name: Unit test
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
Expand All @@ -24,7 +24,7 @@ jobs:
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
Expand All @@ -39,19 +39,19 @@ jobs:
name: Code standard
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
php-version: "8.3"
coverage: none
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
Expand All @@ -66,19 +66,19 @@ jobs:
name: Code coverage
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
php-version: "8.3"
coverage: xdebug
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Get composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache dependencies
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

Utility library for numerics. Float versions of `ceil()`, `floor()` and `rand()` with precision. An open minded numeric parser, formatter, plus some additional functions.

Current version supports PHP `^7.4|^8.0`.
Current version supports PHP `^8.0`.

## Installation

Expand Down Expand Up @@ -218,7 +218,8 @@ $numerics->setLocale('sv_SE'); // Set to Swedish

| Version | PHP | |
| --- | --- | --- |
| `2.3` | `^7.4\|^8.0` | Precision imrovements, negative precision in format() |
| `2.4` | `^8.0` | Multiple-of rounding: `mround()` `mfloor()` `mceil()` methods |
| `2.3` | `^7.4\|^8.0` | Precision improvements, negative precision in format() |
| `2.2` | `^7.4\|^8.0` | Default locale |
| `2.1` | `^7.1\|^8.0` | |
| `2.0` | `^7.1` | Instanceable, `format()` method, ability to specify locale |
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
}
},
"require": {
"php": "^7.4|^8.0"
"php": "^8.0"
},
"require-dev": {
"phpunit/phpunit": "^9.0|^10.0",
"phpunit/phpunit": "^9.0 | ^10.0 | ^11.0",
"php-coveralls/php-coveralls": "^2.4",
"squizlabs/php_codesniffer": "^3.5"
}
Expand Down
File renamed without changes.
66 changes: 55 additions & 11 deletions src/Numerics.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace Phrity\Util;

use DomainException;

/**
* Numerics utility class.
* Float versions of ceil(), floor() and rand() with precision.
Expand All @@ -15,18 +17,18 @@
class Numerics
{
/** @var int $precision Default precision */
private $precision;
private int|null $precision;
/** @var int $digits Relevant digits for floats */
private $digits;
private int $digits;
/** @var array $localization Localization data */
private $localization;
private array $localization;

/**
* Constructor for this class
* @param int|null $precision Default precision
* @param string|null $locale Default locale to use as string
*/
public function __construct(?int $precision = null, ?string $locale = null)
public function __construct(int|null $precision = null, string|null $locale = null)
{
$this->precision = $precision;
$this->digits = PHP_FLOAT_DIG;
Expand Down Expand Up @@ -54,7 +56,7 @@ public function setLocale(string $locale): void
* @param int|null $precision Precision to apply
* @return float Return floor with precision
*/
public function floor(float $number, ?int $precision = null): float
public function floor(float $number, int|null $precision = null): float
{
$f = pow(10, $precision ?? $this->precision ?? 0);
return floor($number * $f) / $f;
Expand All @@ -66,7 +68,7 @@ public function floor(float $number, ?int $precision = null): float
* @param int|null $precision Precision to apply
* @return float Return ceil with precision
*/
public function ceil(float $number, ?int $precision = null): float
public function ceil(float $number, int|null $precision = null): float
{
$f = pow(10, $precision ?? $this->precision ?? 0);
return ceil($number * $f) / $f;
Expand All @@ -76,21 +78,63 @@ public function ceil(float $number, ?int $precision = null): float
* Round function with precision.
* @param float $number The number to apply round to
* @param int|null $precision Precision to apply
* @return float Return round with precision
* @return float Return round with precision
*/
public function round(float $number, ?int $precision = null): float
public function round(float $number, int|null $precision = null): float
{
return round($number, $precision ?? $this->precision ?? 0);
}

/**
* Floor function using multiple-of.
* @param float $number The number to apply floor to
* @param float $multipleOf Rounding target multiple
* @return float Return floor by multiple-of (null if not solvable)
*/
public function mfloor(float $number, float $multipleOf): float
{
if ($multipleOf <= 0) {
throw new DomainException('Argument #2 ($multipleOf) must be a float higher than 0');
}
return round(floor($number / $multipleOf) * $multipleOf, $this->precision($multipleOf));
}

/**
* Ceil function using multiple-of.
* @param float $number The number to apply ceil to
* @param float $multipleOf Rounding target multiple
* @return float Return ceil by multiple-of (null if not solvable)
*/
public function mceil(float $number, float $multipleOf): float
{
if ($multipleOf <= 0) {
throw new DomainException('Argument #2 ($multipleOf) must be a float higher than 0');
}
return round(ceil($number / $multipleOf) * $multipleOf, $this->precision($multipleOf));
}

/**
* Round function using multiple-of.
* @param float $number The number to apply round to
* @param float $multipleOf Rounding target multiple
* @return float Return round by multiple-of (null if not solvable)
*/
public function mround(float $number, float $multipleOf): float
{
if ($multipleOf <= 0) {
throw new DomainException('Argument #2 ($multipleOf) must be a float higher than 0');
}
return round(round($number / $multipleOf) * $multipleOf, $this->precision($multipleOf));
}

/**
* Random float number generator with precision.
* @param float $min Lowest result
* @param float|null $max Highest result
* @param int|null $precision Precision to use
* @return float|null Random number with precision (null if not solvable)
*/
public function rand(float $min = 0, ?float $max = null, ?int $precision = null): ?float
public function rand(float $min = 0, float|null $max = null, int|null $precision = null): float|null
{
$rand_max = mt_getrandmax();
$max = is_null($max) ? $rand_max : $max;
Expand Down Expand Up @@ -131,7 +175,7 @@ public function precision(float $number, bool $wide = false): int
* @param int|float|string $numeric A numeric representation to parse
* @return float|null Return as float (null if parsing failed)
*/
public function parse($numeric): ?float
public function parse($numeric): float|null
{
$ts_found = false;

Expand Down Expand Up @@ -200,7 +244,7 @@ public function parse($numeric): ?float
* @param int|null $precision Precision to use, no rounding by default
* @return string Numeric string
*/
public function format(float $number, ?int $precision = null): string
public function format(float $number, int|null $precision = null): string
{
$precision = $precision ?? $this->precision ?? $this->precision($number);
return number_format(
Expand Down
9 changes: 6 additions & 3 deletions tests/CeilTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

namespace Phrity\Util;

use Phrity\Util\Numerics;
use PHPUnit\Framework\TestCase;
use Phrity\Util\Numerics;
use TypeError;

/**
* Numerics ceil test class.
Expand Down Expand Up @@ -99,7 +100,8 @@ public function testInstance(): void
public function testInvalidNumberInput(): void
{
$numerics = new Numerics();
$this->expectException('TypeError');
$this->expectException(TypeError::class);
$this->expectExceptionMessage('Argument #1 ($number) must be of type float, string given');
$numerics->ceil('should fail');
}

Expand All @@ -109,7 +111,8 @@ public function testInvalidNumberInput(): void
public function testInvalidPrecisionInput(): void
{
$numerics = new Numerics();
$this->expectException('TypeError');
$this->expectException(TypeError::class);
$this->expectExceptionMessage('Argument #2 ($precision) must be of type ?int, string given');
$numerics->ceil(12.34, 'should fail');
}
}
9 changes: 6 additions & 3 deletions tests/FloorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

namespace Phrity\Util;

use Phrity\Util\Numerics;
use PHPUnit\Framework\TestCase;
use Phrity\Util\Numerics;
use TypeError;

/**
* Numerics floor test class.
Expand Down Expand Up @@ -99,7 +100,8 @@ public function testInstance(): void
public function testInvalidNumberInput(): void
{
$numerics = new Numerics();
$this->expectException('TypeError');
$this->expectException(TypeError::class);
$this->expectExceptionMessage('Argument #1 ($number) must be of type float, string given');
$numerics->floor('should fail');
}

Expand All @@ -109,7 +111,8 @@ public function testInvalidNumberInput(): void
public function testInvalidPrecisionInput(): void
{
$numerics = new Numerics();
$this->expectException('TypeError');
$this->expectException(TypeError::class);
$this->expectExceptionMessage('Argument #2 ($precision) must be of type ?int, string given');
$numerics->floor(12.34, 'should fail');
}
}
9 changes: 6 additions & 3 deletions tests/FormatTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@

namespace Phrity\Util;

use Phrity\Util\Numerics;
use PHPUnit\Framework\TestCase;
use Phrity\Util\Numerics;
use TypeError;

/**
* Numerics format test class.
Expand Down Expand Up @@ -79,7 +80,8 @@ public function testPrecisions(): void
public function testInvalidNumberInput(): void
{
$numerics = new Numerics();
$this->expectException('TypeError');
$this->expectException(TypeError::class);
$this->expectExceptionMessage('Argument #1 ($number) must be of type float, string given');
$numerics->format('should fail');
}

Expand All @@ -89,7 +91,8 @@ public function testInvalidNumberInput(): void
public function testInvalidPrecisionInput(): void
{
$numerics = new Numerics();
$this->expectException('TypeError');
$this->expectException(TypeError::class);
$this->expectExceptionMessage('Argument #2 ($precision) must be of type ?int, string given');
$numerics->format(12.34, 'should fail');
}
}
Loading

0 comments on commit 8a6ad05

Please sign in to comment.