PHPackages                             codeboutique/price-rounder - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. codeboutique/price-rounder

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

codeboutique/price-rounder
==========================

0.3.0(8y ago)53.5k↓33.3%MITPHP

Since Jan 30Pushed 8y ago1 watchersCompare

[ Source](https://github.com/mblarsen/price-rounder)[ Packagist](https://packagist.org/packages/codeboutique/price-rounder)[ RSS](/packages/codeboutique-price-rounder/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (2)Versions (4)Used By (0)

[![build status](https://camo.githubusercontent.com/231a912f52a84a3377b0d3779be526f6dc2eb8cd7495e0d108fac5eddc067a06/687474703a2f2f696d672e736869656c64732e696f2f7472617669732f436f6465426f7574697175652f70726963652d726f756e6465722e737667)](http://travis-ci.org/CodeBoutique/price-rounder) [![Latest Stable Version](https://camo.githubusercontent.com/dd28f407e96372115b8435b00e35535f8f4fd4dfcbbbcc89a5b4fd4b81900d03/68747470733a2f2f706f7365722e707567782e6f72672f636f6465626f7574697175652f70726963652d726f756e6465722f762f737461626c65)](https://packagist.org/packages/codeboutique/price-rounder) [![Total Downloads](https://camo.githubusercontent.com/c091cbfb7eb75cfa44096d188ffdccc3f31355a222709c022c5f98c867065ef7/68747470733a2f2f706f7365722e707567782e6f72672f636f6465626f7574697175652f70726963652d726f756e6465722f646f776e6c6f616473)](https://packagist.org/packages/codeboutique/price-rounder) [![License](https://camo.githubusercontent.com/d712d6230cfb9aa5d754f657b9b412864840422b3d9ca455cf10458a05a2924e/68747470733a2f2f706f7365722e707567782e6f72672f636f6465626f7574697175652f70726963652d726f756e6465722f6c6963656e7365)](https://packagist.org/packages/codeboutique/price-rounder)

PriceRounder
============

[](#pricerounder)

Price rounding lib producing nice prices (pretty prices) with range support. Build for making pretty prices when converting prices from other currencies.

Ships with a **best price strategy** `BestPriceRounder` that gives the best pretty price for most amounts regardless of size. It can be configured to include *types of nice prices*:

- *9s* or 1 cent nice prices, like 5.99 or 5.49 `INCLUDE_NINES`
- *95s* or 5 cent nice prices, like 5.95 `INCLUDE_NINETYFIVES`
- *8s* for the superstitious, like 498 or 3.48 `INCLUDE_EIGHTS`
- Halves, like 4.5 or 550 `INCLUDE_HALVESINCLUDE_HALVES`

By default 9s, 98s and Halves are included `INCLUDE_DEFAULT`.

In case you want more specific control other `Rounder`s are available as well:

- `HalvesRounder`
- `CentsRounder`
- `NinesRounder` extends `CentsRounder`
- `NinetyfiveRounder` extends `CentsRounder`

These can be combined so that a different rounder is used for different ranges using the `RangeRounder`.

Simple and extensible formatting can be done as well: See `Rounder` class.

Example
=======

[](#example)

Instance a rounder and invoke the round method. That's all:

```
$rounder = new NinetyfiveRounder();
$rounder->round(15.12); // returns 14.95

```

Best price example:

```
$rounder = new BestPriceRounder();
$rounder->round(66.33); // return 66.49

$rounder->printAnalysis(66.33);

+----------------------+-----------+------+------------+------+-------+---+
| Candidate for: 66.33 | Base Diff |    % | Total Diff |    % | Score |   |
+----------------------+-----------+------+------------+------+-------+---+
|                65.95 |        -1 | -1.5 |      -0.38 | -0.6 |  0.22 |   |
|                65.99 |        -1 | -1.5 |      -0.34 | -0.5 |  0.18 |   |
|                66.49 |         0 |  0.0 |       0.16 |  0.2 |  0.04 | * |
|                 66.5 |         0 |  0.0 |       0.17 |  0.3 |  0.04 |   |
|                66.95 |         0 |  0.0 |       0.62 |  0.9 |  0.57 |   |
|                66.99 |         0 |  0.0 |       0.66 |  1.0 |  0.65 |   |
|                   67 |         1 |  1.5 |       0.67 |  1.0 |  0.67 |   |
+----------------------+-----------+------+------------+------+-------+---+

$rounder->printAnalysis(1253.2);

+-----------------------+-----------+------+------------+------+--------+---+
| Candidate for: 1253.2 | Base Diff |    % | Total Diff |    % |  Score |   |
+-----------------------+-----------+------+------------+------+--------+---+
|                  1195 |       -58 | -4.6 |     -58.20 | -4.9 | 283.45 |   |
|                  1199 |       -54 | -4.3 |     -54.20 | -4.5 | 245.01 |   |
|                  1249 |        -4 | -0.3 |      -4.20 | -0.3 |   1.41 |   |
|                  1250 |        -3 | -0.2 |      -3.20 | -0.3 |   0.82 | * |
|                  1295 |        42 |  3.4 |      41.80 |  3.2 | 134.92 |   |
|                  1299 |        46 |  3.7 |      45.80 |  3.5 | 161.48 |   |
|                  1300 |        47 |  3.8 |      46.80 |  3.6 | 168.48 |   |
+-----------------------+-----------+------+------------+------+--------+---+

```

The best value score takes into account the least change in price. By default the price rounder gives edge to odd numbers first and then to gain (or to avoid loss) second. This can be configured when creating the rounder object:

```
$rounder = new BestPriceRounder([
    "halves": 3.0,
    "gain": 10.0
]);

```

This will favour values ending in five—4.5 or 450, but first and foremost it will favour prices that does not give a loss.

See more examples in `example.php`:

```
+----------+----------+--------+-------------------+--------------------+
| Original | No edges | odd: 9 | gain: 9, nines: 5 | eights: 5, gain: 5 |
+----------+----------+--------+-------------------+--------------------+
| 5.1      | 4.99     | 5.48   | 5.49              | 5.48               |
| 5.23     | 5.48     | 5.48   | 5.49              | 5.48               |
| 5.6      | 5.5      | 5.5    | 5.49              | 5.48               |
| 6.1      | 5.99     | 5.99   | 5.99              | 5.98               |
| 9.6      | 9.5      | 9.5    | 9.49              | 9.48               |
| 14.51    | 14.49    | 14.49  | 14.49             | 14.49              |
| 27.53    | 27.5     | 27.5   | 27.5              | 27.5               |
| 66.33    | 66.48    | 66.48  | 66.49             | 66.48              |
| 512      | 499      | 499    | 549               | 498                |
| 752      | 749      | 749    | 749               | 749                |
| 1253.2   | 1249     | 1249   | 1249              | 1248               |
| 2502.33  | 2499     | 2499   | 2499              | 2499               |
| 2517.33  | 2499     | 2499   | 2549              | 2548               |
+----------+----------+--------+-------------------+--------------------+

```

Range example:

```
$rounder = new RangeRounder([
    10  => "NinesRounder",
    50  => "NinetyfiveRounder",
    150 => "NinetyfiveRounder::1",
    999 => "NinesRounder::2",
    "*" => "round"   // uses regular PHP function through function_exists()?
]);

$rounder->round(5.6); // returns 5.99
$rounder->round(6.1); // returns 5.99
$rounder->round(9.6); // returns 9.99
$rounder->round(10.3); // returns 9.95
$rounder->round(14.49); // returns 13.95
$rounder->round(14.51); // returns 14.95
$rounder->round(50); // returns 49.95
$rounder->round(75); // returns 79.50
$rounder->round(79); // returns 79.50
$rounder->round(83); // returns 79.50
$rounder->round(92); // returns 89.50
$rounder->round(99); // returns 99.50
$rounder->round(512); // returns 499
$rounder->round(752); // returns 799
$rounder->round(982); // returns 999
$rounder->round(1100); // returns 1100
$rounder->round(2222); // returns 2222
$rounder->round(2502.33); // returns 2502

```

In the above example the rounders are instansiated based on the strings, but you can use preconfigured instances of rounders as well.

String format:

```
Rounder::param[|param2 ...][::[decimals[|dec_point[|thousand_sep]]]]

```

E.g.:

```
"Rounder::::2"    // with value of 5 will output 5.00
"Rounder::::2|,"  // with value of 5 will output 5,00 // changed decimal point to comma
"NinetyfiveRounder"    // with value of 92 will output 92.95
"NinetyfiveRounder::1" // with value of 92 will output 89.5 // changed factor value

```

Note: Be sure to include namespace if you use your own rounders inherting from `Rounder`.

###  Health Score

30

—

LowBetter than 64% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity25

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~302 days

Total

3

Last Release

3158d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/adf399c8b2a9cea04df413eeff3dd2b55bd0146a63234c7a1e610733d31e6b15?d=identicon)[mblarsen](/maintainers/mblarsen)

![](https://avatars.githubusercontent.com/u/59724?v=4)[sof](/maintainers/Sof)[@sof](https://github.com/sof)

---

Top Contributors

[![mblarsen](https://avatars.githubusercontent.com/u/247048?v=4)](https://github.com/mblarsen "mblarsen (13 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/codeboutique-price-rounder/health.svg)

```
[![Health](https://phpackages.com/badges/codeboutique-price-rounder/health.svg)](https://phpackages.com/packages/codeboutique-price-rounder)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
