AL+

Language: RO (română) EN (English)

Email us: paul@alplustech.com

Looking back at the week of 15–21 January 2025

Decimal arithmetic still needs a rounding contract

PHP 8.4.3 fixed specific BCMath edge cases. Define scale, rounding and numeric equality separately from formatting before accepting a money calculation.

Citiți articolul în română

Choosing decimal arithmetic does not decide how a business should round a calculation. An application still needs an explicit rule for intermediate precision, the point of rounding and the representation sent to another system. PHP 8.4.3 is a useful historical reminder: a library can correct specific numeric behavior while the application's business contract remains a separate responsibility.

Looking back from November 2026 at the week of 15 January 2025, the PHP changelog records version 8.4.3 on 16 January. Its BCMath section lists fixes for comparing zero and negative zero, preserving trailing zeros in Number::round(), a rounding-mode zero edge case and dividend-scale calculation. These are specific fixes, not evidence that all money calculations in PHP were broken.

Separate value from its written form

Two decimal strings can express the same numeric value while carrying different formatting. For example, 12.3 and 12.30 are numerically equal, but a receiving interface might require exactly two fractional digits. Equality and serialization therefore need separate acceptance conditions. A comparison that ignores trailing zeros is not evidence that an export has the required shape.

The same distinction applies to zero and negative zero. A mathematical comparison and the chosen display of a result answer different questions. If a ledger import expects a normalized zero, the application should define that requirement explicitly. It should not infer the entire contract from how an object happens to print after an operation.

The January changelog makes these distinctions visible by listing zero comparison and trailing-zero preservation separately. The business inference is that a numeric dependency has several observable responsibilities. When upgrading it, verify the behaviors your application actually uses rather than treating “decimal support” as one indivisible feature.

Decide where precision is lost

Consider an illustrative allocation of a total across several lines. A rule that rounds each line before summing can produce a different result from one that sums higher-precision values and rounds once. Neither rule can be selected merely by installing an arbitrary-precision library. The application needs to say which result belongs in the agreed output.

Write down the input representation, permitted fractional precision and rounding rule at the relevant boundary. Define scale as the number of fractional decimal digits at that stage. Keeping more digits during calculation and emitting two digits at export are separate choices. Define what happens to any remainder when a total must be allocated into fixed units. That is a proposed design exercise, not accounting advice or a report of a financial incident. The correct business rule must come from the product's actual requirements.

Avoid converting a decimal input through a binary floating-point value before giving it to decimal arithmetic. PHP's BCMath manual, read as mutable documentation in November 2026, describes arbitrary-precision numbers represented as strings and warns about passing floats. It helps explain the representation boundary; it is not a frozen record of every January 2025 manual page.

Precision also has an end. An API, database column or export format can constrain the value after the calculation completes. If that boundary silently truncates digits, careful internal arithmetic may not preserve the intended result. Review the whole path from accepted input to stored and transmitted output, including the conversion rules at each boundary.

Upgrade against named expectations

For an application using the affected operations, the release suggests a focused set of checks. Include a zero comparison, a value whose output requires trailing zeros, and a rounding boundary relevant to the selected mode. Add the actual division or allocation path if the application depends on it. These are proposed checks, not tests performed by AL+ for this article.

Keep expected numeric results separate from expected strings. A test asserting only that two values compare equal can miss a serialization requirement. A string comparison alone can reject a numerically valid result without explaining whether the difference matters to the business operation. Each expectation should name the contract it protects.

The PHP release archive supplies a second official historical record of the release date. Its surrounding entries continue to change. In November 2026, 8.4.3 is a historical patch, not a recommendation to select that old version for a new deployment. Use a supported, appropriately patched runtime and assess the actual application before accepting an upgrade.

Fixed minor units can be simpler

The strongest counterargument to arbitrary-precision decimal objects is that many products only need fixed minor units. An integer count of cents, paired with an explicit currency and range limits, can make addition and storage straightforward. Introducing another numeric abstraction may increase complexity without improving the operations the product actually performs.

That approach still needs rules for multiplication, division and allocation. A percentage or a unit price with finer precision can create a fractional result before it becomes a whole number of minor units. Decide where that conversion occurs. Also avoid assuming every supported currency or quantity shares the same scale.

Choose the representation by the operations and interfaces, not by a claim that one numeric type makes money universally safe. Fixed units can be appropriate for settled amounts; decimal representations can be useful where the calculation requires finer precision. Mixing them can also be reasonable when the conversion boundary is explicit and understandable.

For custom software development, ask for a short calculation contract before choosing the library: accepted input, intermediate precision, rounding point, remainder rule and output representation. Then use release notes to identify which dependency behaviors need checking. PHP's January patch is valuable evidence about particular edge cases; the application owner still has to define what a correct result means.