Shipmind Labs

Splitting money is not division. It is handing out every minor unit and being able to say who got the last one.

The failure is familiar. You split 100 across three parts, round each one, and suddenly the parts no longer sum to what you received. Someone patches it by adding a cent to the first row. Then a negative amount arrives (a refund, a reversal) and the patch allocates in the wrong direction.

In our open-source project amountfield we made that arithmetic explicit. Everything is bigint minor units, so there is no float to lose. Allocation floors each share, then hands the leftover units to the largest remainders. The parts sum back to the original exactly: for equal parts, for weights like 3 and 7, and for negative amounts. No two equal shares end up more than one unit apart.

What the API refuses is the more useful part.

Multiplying by a ratio accepts text, a bigint, a whole number, or a numerator and a denominator, but not the JavaScript number 0.1, because that value is not 0.1. It also throws if you did not name a rounding mode, since there is no safe default when the result lands between two units. Addition refuses to mix currencies outright.

Our take: in money code, a thrown error at the boundary is cheaper than a silent cent. Rounding policy is a product decision, so the library should probably make you state it rather than guess on your behalf.

Somewhere your codebase already decides rounding, either down in the domain layer or wherever the formatting happens.

Was this useful?

Building something similar?

or email hello@shipmindlabs.com