Blog

Same expenses, same answer: how kisir settles up without guessing

Put the same expenses into kisir on two phones, a year apart, and you get the same who-owes-whom and the same settlement plan, to the cent. That's not an accident of the code. It's the one property a shared ledger has to have, and the reason there's no model in the middle of it.

By David Piliposyan ·

The property, stated plainly

A shared expense list is only useful if everyone in the group believes it. And they believe it for one reason: anyone can check it. Dan can take the list of expenses, do the sums himself, and arrive at the same balances the app shows.

That means the app has to be deterministic: the same expenses must always produce the same balances and the same settlement plan. No randomness, no “usually”, no model that might reason slightly differently on Tuesday. This is the whole argument for keeping AI out of the arithmetic, so this post walks through how kisir actually computes who owes whom, step by step, with a group you can check by hand.

Step one: everything in whole cents

Computers are bad at decimals. The classic example is that 0.1 plus 0.2 doesn’t come out to exactly 0.3 in floating-point arithmetic. For a bank balance over a year that’s a rounding error. For a group where every balance must add to zero, it’s a list that doesn’t reconcile.

So kisir never adds decimals. Every amount is turned into whole cents first (€14.90 becomes 1,490), all the arithmetic happens in integers, and the result is turned back into euros at the end. Integer addition is exact. The sum of everyone’s balances is zero, every time, as a guarantee rather than a hope.

Step two: the balance of each person

Take four friends. Ana paid €120.00 for the villa, for all four. Ben paid €40.00 for groceries, for all four. Cara paid €60.00 for a dinner that only Ana, Ben and Cara ate.

Each person’s balance is what they paid minus what they owe across all expenses.

Villa (€120.00 ÷ 4)Groceries (€40.00 ÷ 4)Dinner (€60.00 ÷ 3)PaidBalance
Ana€30.00€10.00€20.00€120.00+€60.00
Ben€30.00€10.00€20.00€40.00−€20.00
Cara€30.00€10.00€20.00€60.00€0.00
Dan€30.00€10.00—€0.00−€40.00

In cents: Ana is +6,000, Ben −2,000, Cara 0, Dan −4,000. They sum to zero. Good.

Step three: when the division isn’t clean

The example above divides neatly. Life doesn’t. Three people share a €23.00 taxi: 2,300 cents divided by three is 766 cents each with 2 cents left over.

A model, or a careless program, might round everyone to 767 and create a cent out of nothing, or round down to 766 and lose two. kisir has one fixed rule: the leftover cents go to the first people in a fixed order, one cent each. Two people owe €7.67 and one owes €7.66. The total is still 2,300, and because the order is fixed, the same taxi gives the same three shares on any phone, any day.

For Shares, the same rule applies after weighting: if Ana counts for two and Ben and Cara for one each, a €100.00 bill is 10,000 cents split 4 ways by weight, Ana 5,000 and the others 2,500. For Amounts, you type the figures yourself and the editor won’t save until they add up to the total. There is no third path where the app decides.

Step four: currencies that have no cents

Here’s a case where “just do the math” is wrong, and a rule is right. The Armenian dram has no coin below one dram. Settling an Armenian group to the hundredth once produced an instruction to transfer 1,541,315.99 drams, which nobody can obey.

So before settling, balances are snapped to what the currency can actually pay: whole drams for drams, cents for euros. The rule is a short explicit table, not something inferred, and it’s part of why the plan is always something a person can hand over. The post nobody can pay 0.99 of a dram tells the whole story.

For expenses in a foreign currency, kisir fills in today’s rate and converts to the group’s currency. You can change the rate to what your bank charged, and the ledger shows both figures. That rate is the only outside number in the whole computation, it’s a lookup, and you can override it. The multi-currency guide covers it.

Step five: the fewest transfers

Now the balances: Ana +€60.00, Ben −€20.00, Cara €0.00, Dan −€40.00. Who pays whom?

The obvious way is “everyone pays back everyone they owe per expense”, which here would be four payments (Ben and Dan to Ana for the villa, Ana and Dan to Ben for groceries, and so on, netting out). kisir instead takes the balances and matches the biggest debtor with the biggest creditor, repeatedly, until every balance is zero. Here that’s two payments:

How it ends

Dan → Ana€40.00
Ben → Ana€20.00

Cara pays nobody and receives nothing, because she’s even. The procedure is the same every time for the same balances, and the settle-up guide walks through it by hand so you can reproduce the app’s plan yourself. “Your plan” in the app is just your lines from this list, and one tap records each payment. When every balance is zero, the group closes itself.

Why none of this is a job for a model

Look at what each step needed: exact addition, a fixed tie-break for leftover cents, a table of which currencies have cents, and a short procedure for matching debtors to creditors. Every one of them is a rule you can read and apply with a pencil.

A model would get the villa example right. It would probably get the taxi right. It might get the dram right. “Probably” and “might” are the problem. The moment Dan can’t reproduce the number, the list stops being a shared fact and becomes something the app said. Then the group is back to arguing, with an extra participant that can’t be argued with.

Deterministic arithmetic is less impressive on an app store page. It’s the only kind that keeps four friends looking at the same number and agreeing it’s right. That’s the job, and it’s why kisir does it with rules instead of guesses.

See your plan in one tap

kisir shows who owes whom and the fewest transfers to settle, the same answer every time. No account, no ads, no AI.

Get kisir