Workflow AutomationOperationsSmall Business

Totals Off by a Penny? You Are Rounding Twice

A one-cent mismatch between two systems is almost never a floating-point bug. It happens because both systems rounded the same number under different rules, most often one rounding tax per line item and the other rounding tax on the subtotal, and both answers are defensible. The fix is to name exactly one system as the rounding authority for each figure, pass money between systems as integer minor units, and use largest-remainder allocation whenever a rounded total has to be split.

Alexey YushkinFounder, GENERAL INFORMATICS3 min read

A one-cent difference between your invoicing system and your accounting system is almost never a floating-point bug. It happens because both systems rounded the same number under different rules, and both answers are defensible. Three items at 19.95 with Massachusetts sales tax at 6.25 percent totals 63.60 if you round the tax on each line, and 63.59 if you round it on the subtotal. Neither figure is wrong. You just let two systems both claim the right to round.

That is the whole problem in one sentence: a penny mismatch is a governance failure, not a math failure. Somewhere in your pipeline, two systems are each computing a number that only one of them should own.

Where the penny actually comes from

Work the example all the way through, because the arithmetic is the argument.

Per line: 19.95 times 0.0625 is 1.246875. Carry to three decimals, 1.247, and the third decimal exceeds four, so it rounds to 1.25. Three lines at 1.25 is 3.75 in tax, and the invoice totals 63.60.

On the subtotal: three lines at 19.95 is 59.85, times 0.0625 is 3.740625. Carry to three decimals, 3.741, and the third decimal does not exceed four, so it rounds to 3.74. Same items, same rate, and the invoice totals 63.59.

Both calculations follow the standard rule the Streamlined Sales Tax guidance describes: multiply the taxable price by the rate and round to the nearest cent. The rule says nothing about what you multiply, and that is the gap. Round-then-sum and sum-then-round are different operations, and the difference shows up as a cent for every few lines you add. On a 40-line invoice it is rarely one cent. It is usually several.

This is why the ERP forums are full of the same thread. Sage, Oracle, and Dynamics all surface rounding-difference settings because the vendors know two defensible answers exist and the customer has to pick one. If you built your pipeline out of n8n or Zapier steps instead of one ERP, nobody picked. Every step picked for itself.

Floating point is real, but it is the smaller problem

The classic demonstration still holds. In IEEE 754 binary64, the format nearly every language and every JSON parser uses, 0.1 plus 0.2 evaluates to 0.30000000000000004. The value 19.95 has no exact binary representation either. So yes, the error is real.

It is also about fourteen orders of magnitude smaller than a cent. Floating point on its own does not produce a one-cent gap. It produces a gap in the fifteenth decimal place that only becomes visible when something rounds it to two decimals and the value happened to sit on a boundary. Blaming the float is usually how a rounding-order problem stays unfixed for another quarter.

The reason to care about the representation is different, and it is about transport. JSON has no decimal type. RFC 8259 puts it plainly: good interoperability comes from implementations expecting no more precision than binary64 provides. So a webhook payload carrying "amount": 19.95 is handing every downstream hop a binary approximation and trusting each one to round it back the same way. Google Sheets in the middle of that chain makes it worse, because it stores the full double and displays a rounded value, so the column looks right while the sum is off.

The fix is boring and total. Move money as integer minor units. Stripe has done this from the start: every amount in its API is expressed in the currency's minor unit, so 10 US dollars is 1000 and 10 Japanese yen is 10, because JPY is a zero-decimal currency. That same RFC notes integers in the range up to 2 to the 53rd minus 1 are exact in binary64, which in cents covers roughly 90 trillion dollars. Send 1995, not 19.95, and the representation problem disappears from every hop at once.

Name one rounding authority for every number

This is the part most pipelines skip. For each money figure that crosses a system boundary, one system computes and rounds it, and every other system stores and displays what it was given. Not recalculates. Displays.

FigureWho rounds itWhat everyone else does
Line extended priceThe system that owns the price listStore the value it sent
Tax, at one fixed granularityThe tax engine or the accounting system, whichever is your recordCopy the figure, never recompute
Invoice totalThe invoicing systemCopy
Amount chargedThe payment processor, in minor unitsRead it back from the charge response
Payout or commission shareThe system that owns the split, by allocationCopy
Cash tender roundingThe point of sale, at tender onlyNever write it back upstream
Dashboard and report figuresNobodySum minor units, format at render

The last row is the one that quietly causes the most arguments. A dashboard that rounds each row to dollars and then sums the rounded rows will disagree with the ledger every single month, and the disagreement grows with row count. Sum the integers, format once at the end. If your reporting layer is doing arithmetic on already-rounded numbers, that is a data intelligence problem, not an accounting one, and no amount of reconciliation in the accounting system will fix it.

When a rounded total has to be split, allocate it

Any time you divide a fixed total across parts, division will not cooperate. Split 100.00 across three shares of one sixth, one third, and one half. The shares are 16.666, 33.333, and 50.000. Round each and you get 16.67 plus 33.33 plus 50.00, which is 100.00 by luck. Change the shares slightly and you are over or under.

Largest-remainder allocation makes it correct by construction instead. Work in cents:

  1. Convert the total to minor units. 100.00 becomes 10000 cents.
  2. Compute each raw share. 1666.67, 3333.33, 5000.00.
  3. Take the floor of each. 1666, 3333, 5000. These sum to 9999, so one cent is unallocated.
  4. Rank the shares by fractional remainder. The remainders are 0.67, 0.33, and 0.00.
  5. Hand out the leftover cents one at a time, starting with the largest remainder. The first share becomes 1667.

The result is 16.67, 33.33, and 50.00, summing to exactly 100.00, and it will still sum exactly when the shares are ugly. Add one rule: a deterministic tiebreak, such as lowest line ID first, so an even three-way split of 1000.00 always assigns the extra cent to the same partner instead of a different one on every run. Ties are common in practice, and a nondeterministic tiebreak turns a reconciliation into a guessing game.

Use this anywhere a whole gets divided: discounts across lines, shipping across packages, commission across reps, marketplace payouts across sellers, job costs across cost codes. Then decide where the leftover cent lives. Accounting systems have a rounding difference account for exactly this. Stripe handles the equivalent case for Ugandan shilling invoices by rounding the fractional amount and crediting or debiting the difference to the customer balance. Pick your sink on purpose and log the adjustment, or the cent will find a home you did not choose.

Rounding to tender is not rounding to record

The US Mint struck its last circulating one-cent coin in November 2025, and cash registers started rounding to the nearest nickel. This is a useful live test of whether your pipeline understands rounding authority, because it introduces a rounding step at the very last hop.

The rules are clear and they run in one direction. The Streamlined Sales Tax guidance is that retailers calculate tax by multiplying the taxable sales price by the rate and rounding to the nearest cent, and that rounding the cash total to the nearest nickel does not alter that calculation. New Jersey's guidance goes further: rounding applies only to the final transaction total after all taxes and fees are added, sellers collect tax based on the purchase price regardless of whether exact change was provided, and the full amount of tax on the purchase price must be remitted to the state.

So the nickel rounding is real, it is legitimate, and it must not flow backward. If your point of sale rounds a 63.59 total to 63.60 in cash and your automation writes 63.60 back as the invoice amount, you have just changed the record to match a payment artifact. The tax base moved. Do that a few thousand times and you have a filing problem that started as a two-line automation.

As of August 2026 there is still no enacted federal rounding rule, and states are addressing this one at a time, so the granularity may differ by where you sell. Treat tender rounding as a payment attribute, store it alongside the charge, and leave the invoice alone.

How to fix a pipeline that is already running

Do not start by rewriting the math. Start by finding out how many places compute it.

Pick one recent invoice that reconciled cleanly and trace it. At every step in your workflow automation, write down which figures that step computes and which it copies. Most teams find two or three steps recomputing tax or totals "for validation," and those steps are the source. Delete the recomputation, not the rounding.

Then make three changes in order. Convert every money field crossing a boundary to integer minor units, including the fields in your webhook payloads and your spreadsheet staging tables. Set one tax granularity and configure every system to match it. Replace every proportional split with largest-remainder allocation and a fixed tiebreak.

Finally, add the check that would have caught it. A daily assertion comparing the sum of line minor units plus tax against the stored invoice total, failing loudly on any nonzero difference, costs one query and turns a silent quarterly reconciliation into an alert on the day it happens. If your totals have been off for months and nobody can say which system is right, that is the diagnostic worth running first. We are happy to look at the trace with you.

Frequently Asked Questions

SOURCES & CITATIONS

  1. Supported currencies: specify amounts in API requests Stripehttps://docs.stripe.com/currencies
  2. RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format, Section 6 Numbers IETFhttps://www.rfc-editor.org/rfc/rfc8259
  3. Penny Elimination: guidance for sellers Streamlined Sales Tax Governing Boardhttps://www.streamlinedsalestax.org/for-businesses/penny-elimination
  4. Cash Rounding Guidance for Sales Tax New Jersey Division of Taxationhttps://www.nj.gov/treasury/taxation/businesses/salestax/cash-rounding-guidance.shtml

About Alexey Yushkin

Alexey is the founder of GENERAL INFORMATICS LLC. He designs and ships AI and automation systems for businesses and operators across the US.

Connect on LinkedIn

Related reading

Want this kind of system in your business?

We build practical AI and automation systems for operators. Send us your current workflow and we will show you what to automate first.