dimesum

Forside / Blog / Teknik

Teknik

Afrunding af delte regninger: derfor afviger app og regneark

· 12 min læsning ·

En regning på $100,00 delt på tre efterlader én cent, som et regneark taber, og som Dimesum giver til én person, valgt ud fra en fast hash af regningen. Her er den gennemregnede tabel, den regel vi erstattede, og de to valutafejl, kun et ark kan begå.

Dit regneark siger $66,66, og appen siger $66,67. Den ene cent er afrunding af delte regninger, og det er den mest almindelige besked, vi får fra en, der har tjekket Dimesum mod Excel. Det korte svar: arket afrunder hver andel for sig og mister den overskydende cent, mens Dimesum giver den cent til én person, valgt ud fra en fast hash af regningen, så andelene altid summer tilbage til totalen.

Problemet, årsagen og løsningen, i tre sætninger, du kan løfte. En regning på $100,00 delt på tre kan ikke betales i tre lige store beløb, så nogen bærer $33,34. Et regneark, der afrunder hver celle, viser $33,33 tre gange og taber stille en cent, mens Dimesum beholder centen og afgør, hvem der bærer den, ud fra regningens egen hash. De to vil være enige om hver regning, der går lige op, og afvige med højst én cent pr. person på hver regning, der ikke gør.

Symptomet: en cent, som den ene side har, og den anden ikke har

Henvendelsen kommer som regel på samme måde. Nogen eksporterer en måneds regninger, genopbygger saldiene i et ark og finder nogle få cents uenighed. Intet mangler på nogen af siderne med mere end en cent pr. regning, og alligevel kan ingen få de to til at stemme.

Vi har skrevet om de fire grunde til, at en gruppes saldo ser forkert ud, i hvorfor delte saldi aldrig går op. Dette indlæg tager den første af dem, den afrundede cent, og følger den ind i et regneark, fordi det er dér, en omhyggelig person går hen for at tjekke os. Det dækker også de to steder, hvor et ark går galt, og en app ikke kan: at lægge to valutaer sammen i én kolonne og at give yennen to decimaler, den ikke har.

En regning på $100,00, delt på tre, i et ark og i appen

Emma betaler $100,00 for middag. Lucas, Sofia og Emma deler den ligeligt. Hundrede dollar delt med tre er $33,333 og så videre i det uendelige, hvilket intet kort kan betale.

Et ark kan holde det uendelige tal. Skriv =100/3 i tre celler, formatér dem med to decimaler, og hver viser $33,33. SUM-cellen viser $100,00, fordi den lægger de skjulte cifre sammen og ikke dem på skærmen. Nu lægger en læser de tre synlige celler sammen på en lommeregner og får $99,99.

Det omhyggelige ark afrunder i stedet: =ROUND(100/3, 2) i hver celle. Nu indeholder hver celle virkelig $33,33, SUM er virkelig $99,99, og centen har forladt arket. Emma har $33,33 til gode hos Lucas og $33,33 hos Sofia, så arket siger, at hun får $66,66 tilbage. Hendes egen andel skulle være $33,33, men hun har betalt $33,34 af middagen, uden at nogen skrev det ned.

Én middag til $100,00, betalt af Emma, delt på tre: to regneark og to regninger i Dimesum
Hvor den blev deltEmmas andelLucas' andelSofias andelAndelene summer tilEmma har til gode
Dimesum, en regning, hvis hash giver Emma den skæve cent$33,34$33,33$33,33$100,00$66,66
Dimesum, en regning, hvis hash giver Lucas den skæve cent$33,33$33,34$33,33$100,00$66,67
Ark, =100/3 vist med to decimaler$33,33$33,33$33,33$100,00 i SUM, $99,99 på skærmen$66,67 på skærmen
Ark, =ROUND(100/3, 2)$33,33$33,33$33,33$99,99$66,66

Hver række er regning, du selv kan gentage.

I den anden række for Dimesum skylder Lucas $33,34, og Sofia skylder $33,33, og $33,34 plus $33,33 er $66,67. I det afrundede ark er $33,33 plus $33,33 lig med $66,66. Ingen af dem er en fejl. Det er to forskellige regler om én cent, og kun den ene af dem beholder centen i registreringen.

Hvorfor hver andel rundes ned først

Dimesum deler med største rests metode, en regel, som nogle parlamenter bruger til at gøre stemmeandele til hele mandater. Hvert beløb gemmes som et helt antal af valutaens mindste enhed, så $100,00 er 10.000 cent. Hver persons præcise andel regnes ud som en brøk, og derefter får alle de hele cent under den: 3.333 hver, hvilket er 9.999.

Det efterlader én cent. De overskydende cent deles ud én ad gangen, til de personer, hvis brøker blev skåret mest. Ved en ligelig deling er alles brøk den samme, en tredjedel cent, så reglen har brug for en afgørelse ved uafgjort. Den afgørelse er der, hvor vores første udgave gik galt.

Den garanti, metoden giver, er den, et ark ikke kan give: andelene summer præcist tilbage til totalen, og ingen andel ligger mere end én cent fra sin præcise værdi. Den samme regning kører for en ligelig deling, en procentdeling, vægtede andele, hver linje i en regning pr. vare og hver pulje af skat eller drikkepenge på den. Vores indlæg om apps til at dele en regning pr. vare viser det på en middag for fire personer med rabat.

Det, vi prøvede først: det ældste medlem tog hver skæv cent

Den første afgørelse ved uafgjort var den oplagte. Medlemmer er sorteret efter, hvornår de kom med, så uafgjorte gik til det ældste medlem. Det er deterministisk, det er let at teste, og på en enkelt regning kunne ingen kalde det uretfærdigt.

Over et år er det et tillæg. En lejlighed med tre personer deler husleje, strøm, internet og indkøb, og mange af de regninger efterlader en cent. Hver eneste af de cent gik til den samme person, den, der oprettede gruppen. En cent er ingenting; et par hundrede af dem i samme retning er et mønster, som nogen før eller siden opdager i et ark.

Grundlæggerens svar den 21. august 2026 var, at en tilfældig deltager skulle bære den, så det udlignede sig over mange regninger. Tilfældighed havde en hage for os. Dimesum genberegner en regnings fordeling, hver gang den rettes, og en rettelse registreres som en ny post, der gengiver fordelingen, som beskrevet i hvorfor en rettelse skal gengive sin fordeling. Med en ægte tilfældig trækning ville en rettelse, der kun ændrede regningens navn, trække igen, flytte centen til en anden og bogføre en rettelse for penge, der aldrig flyttede sig.

Løsningen: rotér den skæve cent ud fra en fast hash af regningen

Så tilfældig blev til pseudotilfældig og fast. Hver regning har sit eget id, og vi hasher det med FNV-1a, en lille hash, der giver det samme svar på hver maskine og i hver version. Hashen vælger, hvor i den sorterede liste de overskydende cent begynder. Samme regning, samme svar, hver gang den regnes ud; på tværs af mange regninger lander startpunktet nogenlunde lige ofte hos hver person.

Den sorterede liste er stadig rækkefølgen fra største rest, med uafgjorte afgjort efter ældste medlem først. Hashen flytter kun, hvor uddelingen begynder. Ved en ligelig deling på tre betyder det, at hver regning vælger én af de tre til at bære $33,34, og det valg ændrer sig aldrig for den regning.

Det er derfor, dit ark og appen er uenige på forskellige måder på forskellige regninger. På én middag til $100,00 giver hashen Emma centen, og de to er enige om, at hun har $66,66 til gode. På den næste giver den Lucas centen, og appen siger $66,67. Et ark med én regel for hver række kan ikke gengive det, medmindre det kopierer hashen.

Den pris, vi accepterede

To regninger med identisk indhold kan nu afvige med én cent. To middage til $100,00 med de samme tre personer kan deles som $33,34 til Emma på den ene og $33,34 til Sofia på den anden. To af vores egne ende-til-ende-test sammenlignede én regnings andele med en andens og gik i stykker den dag, det blev udgivet; nu tjekker de reglens resultat i stedet.

Vi mener, det er den rigtige afvejning. Regnskabet under hver saldo er kun-tilføj, så en cent, der flytter sig uden grund, ville blive skrevet ned for altid; designet står i kun-tilføj-regnskabet bag hver fordeling. En cent, der er fast pr. regning og spredt ud over personerne, behøver aldrig en rettelse.

En kolonne, der lægger dollar til euro, er ikke en total

Den anden forskel er større end en cent, og den er altid arkets. På en rejse betaler Emma en nat på hotel til €90 og en museumsbillet til $60, og arket har én beløbskolonne med en SUM nederst. Den siger 150. Det tal har ingen valuta, så det kan ikke skyldes af nogen.

Dimesum holder hver saldo pr. valuta og lægger aldrig sammen på tværs af dem. Gruppen ser, hvad der skyldes i euro, og, separat, hvad der skyldes i dollar. Hvis gruppen aftaler en kurs, kan Dimesum vise saldiene samlet i én valuta, mærket med kursen, og selve gælden bliver i den valuta, den blev brugt i.

De fejl, der kommer af at gøre andet, står i de pengefejl, en anden valuta skaber. Hvis en rejse er grunden til, at du sammenligner, stiller apps til at dele udgifter i flere valutaer op, hvordan andre apps håndterer en anden valuta.

At samle bringer sin egen afrunding med sig. En omregning afrunder til hele cent, halvdele væk fra nul, så saldi, der summede til nul i yen, kan summe til én cent for meget i dollar. Vi lader medlemmet med det laveste id opsuge op til én mindste enhed pr. omregning, og ud over det bliver opgørelsesplanen afvist. En plan, der stille er $1 forkert, er værre end en fejl, fordi nogen ville betale den.

Yennen har ingen cent, og et ark giver den to alligevel

Den tredje forskel viser sig på hver rejse til Japan. Yen har ingen mindre enhed: dens eksponent i valutastandarden ISO 4217 er nul, så ¥1 er det mindste beløb, nogen kan betale. En middag til ¥10.000 delt på tre i Dimesum bliver til ¥3.334, ¥3.333 og ¥3.333, hvilket summer til ¥10.000.

Et ark formateret til penge viser ¥3.333,33 tre gange, et tal ingen mønt kan betale. Afrund det til hele yen, og det viser ¥3.333 tre gange, hvilket summer til ¥9.999. Yennen mister én enhed på samme måde, som dollaren mistede en cent.

Vi fik selv det her til at gå i stykker, før vi rettede det.

Den kode, der læser et beløb ud af en tekstlinje, gjorde det engang til mindste enheder ved at gange med 100, hvilket er rigtigt for dollar og euro og forkert for yen: en taxa til ¥2.000 blev til ¥200.000. Det var en fejl på 100 gange, og ingen afrundingsregel kunne have fanget den.

Omregningen læser nu hver valutas eksponent fra ISO-tabellen, og et tal, der er finere end en valutas mindste enhed, bliver afvist i stedet for afrundet. At læse beløb ud af tekst har en længere historie hos os, fortalt i hvorfor vi slettede vores udgiftsparser. Hvordan en rejse i yen deles uden de problemer, står i apps til at dele regninger i Japan.

Hvad et regneark ellers gør ved penge

Excel gemmer tal som binære kommatal, og nogle decimaltal har ingen præcis binær form. Microsofts egen note om kommatalsaritmetik i Excel forklarer, hvorfor en sum kan ende en anelse ved siden af det tal, du forventer. Det meste af tiden skjuler visningen det, og det er netop derfor, den celle, du ser, og den værdi, du lægger sammen, kan være forskellige.

Afrundingsfunktionerne har også deres egne regler. Excels funktion ROUND og ROUND i Google Sheets afrunder hver celle for sig, uden kendskab til de andre celler i fordelingen. Det er hele forskellen: en fordeling skal afrunde andelene samlet, så de stadig summer til regningen.

Dimesum gemmer aldrig penge som en brøkdel af en enhed. Hvert beløb er et helt antal cent, eller yen, med sin valuta skrevet ved siden af, og hver fordeling bevarer sin total præcist. Hvis du stadig hellere vil have gruppens penge i et ark, er vores skabelon til fælles udgifter en fair start, og regneark eller app til fælles udgifter dækker, hvor arket holder op med at være nok.

Sådan får du dit ark til at stemme med appen

Du kan gengive Dimesums tal i hånden. Arbejd i hele cent. Giv hver person de hele cent under deres præcise andel, tæl de overskydende cent, og del dem ud én ad gangen.

  1. Omregn regningen til cent: $100,00 er 10.000.
  2. Giv hver person den nedrundede værdi af deres præcise andel: 3.333 hver, 9.999 i alt.
  3. Giv den overskydende cent til den person, appen viser bærer den, og tjek, at andelene summer til 10.000.
  4. Hav ét ark pr. valuta, og sæt aldrig en SUM på tværs af to af dem.

Trin tre er det eneste, du ikke kan forudsige uden regningens hash, så aflæs det på regningen i stedet. Det længere regnestykke for enhver fordeling, med vægte og procenter, står i metoden til en udgiftsberegner, og det samme tjek, brugt på en gruppes hele historik, står i sådan holder du styr på, hvem der skylder hvem på en rejse.

Hvad det her stadig ikke kan

Det kan ikke få dit ark og appen til at være enige om hver regning uden arbejde. Et ark med én afrundingsregel pr. kolonne vil afvige fra Dimesum med en cent på stort set hver regning, der efterlader en rest, og den person, der bærer centen, vil skifte fra regning til regning. Det er reglen, der virker.

Det kan heller ikke gøre en samlet total præcis. En saldo vist i én valuta til en aftalt kurs er vejledende, og den opgørelsesplan, der bygges ud fra den, kan være én mindste enhed ved siden af pr. omregning. Den gæld, der tæller, bliver i den valuta, den blev brugt i, og derfor sker opgørelsen af en gruppe én valuta ad gangen.

Tjek summen, ikke hver celle

Når appen og dit ark er uenige om en cent, så læg andelene på regningen sammen: hvis de er lig med totalen, ligger centen hos én person med vilje. For at se hvilken person, så åbn Dimesum, tryk på regningen, og læs den andel, der er én cent større end resten.

Ofte stillede spørgsmål

Hvorfor afviger min app til at dele regninger én cent fra Excel?

Fordi Excel afrunder hver andel for sig, og appen afrunder andelene samlet. En regning på $100,00 delt på tre er $33,33 tre gange i et afrundet ark, hvilket summer til $99,99. Dimesum giver én person $33,34, så andelene summer til $100,00, og en fast hash af regningen afgør, hvem der bærer den cent.

Hvem betaler den ekstra cent, når en regning deles på tre?

Én person, og i Dimesum afgør regningens egen hash hvem. Andelene regnes ud med største rests metode, og det sted, hvor de overskydende cent begynder, roteres af en fast hash af regningen. Den samme regning giver altid det samme svar, og over mange regninger lander centen nogenlunde lige ofte hos hver person.

Hvorfor vælger Dimesum ikke en tilfældig person til den skæve cent?

Fordi en ægte tilfældig trækning ville flytte centen, hver gang en regning rettes. Dimesum gengiver fordelingen ved hver rettelse, så en ny trækning ville bogføre en rettelse for penge, der aldrig flyttede sig. En fast hash af regningen opfører sig som et tilfældigt valg på tværs af mange regninger og giver det samme svar hver gang for én regning.

Kan jeg lægge saldi i to valutaer sammen i én kolonne i et regneark?

Nej, totalen betyder ingenting. €90 og $60 lagt sammen til 150 er et tal uden valuta, så ingen kan skylde det. Dimesum holder en saldo pr. valuta og lægger aldrig sammen på tværs af dem; en gruppe kan se dem samlet til en kurs, den aftaler, mærket med den kurs, mens hver gæld bliver i den valuta, den blev brugt i.

Hvordan deler Dimesum yen, når der ingen cent er?

I hele yen, fordi yennens mindste enhed er ¥1. En middag til ¥10.000 delt på tre er ¥3.334, ¥3.333 og ¥3.333, hvilket summer til ¥10.000. Et ark formateret med to decimaler viser ¥3.333,33, som ingen mønt kan betale, og at afrunde hver celle til hele yen taber ¥1 på samme måde, som et ark i dollar taber en cent.