dimesum

Home / Blog / Ingegneria

Ingegneria

Arrotondamento del conto diviso: app e foglio non coincidono

· 12 min di lettura ·

Un conto da $100.00 diviso in tre lascia un centesimo che un foglio di calcolo perde e che Dimesum dà a una persona, scelta da un hash fisso del conto. Ecco la tabella con i numeri, la regola che abbiamo sostituito e i due errori sulle valute che solo un foglio può fare.

Il tuo foglio di calcolo dice $66.66 e l'app dice $66.67. Quel centesimo è l'arrotondamento del conto diviso, ed è il messaggio più comune che riceviamo da chi ha confrontato Dimesum con Excel. La risposta breve: il foglio arrotonda ogni quota per conto suo e perde il centesimo avanzato, mentre Dimesum consegna quel centesimo a una persona, scelta da un hash fisso del conto, così le quote danno sempre il totale.

Il problema, la causa e la soluzione, in tre frasi che puoi riprendere. Un conto da $100.00 diviso in tre non si può pagare in tre importi uguali, quindi qualcuno si fa carico di $33.34. Un foglio di calcolo che arrotonda ogni cella mostra $33.33 tre volte e perde un centesimo senza dirlo, mentre Dimesum tiene il centesimo e decide chi se ne fa carico in base all'hash del conto stesso. I due coincideranno su ogni conto che si divide in modo esatto e differiranno al massimo di un centesimo a persona su ogni conto che non si divide.

Il sintomo: un centesimo che una parte ha e l'altra no

La segnalazione arriva di solito nello stesso modo. Qualcuno esporta un mese di conti, ricostruisce i saldi in un foglio e trova qualche centesimo di disaccordo. Da nessuna delle due parti manca più di un centesimo per conto, eppure nessuno riesce a farle coincidere.

Abbiamo scritto delle quattro ragioni per cui un saldo di gruppo sembra sbagliato in perché i conti condivisi non tornano mai. Questo articolo prende la prima, il centesimo arrotondato, e la segue dentro un foglio di calcolo, perché è lì che una persona scrupolosa va a controllarci. Copre anche i due punti in cui un foglio sbaglia e un'app non può farlo: sommare due valute in una colonna, e dare allo yen due decimali che non ha.

Un conto da $100.00, in tre, in un foglio e nell'app

Emma paga $100.00 per la cena. Lucas, Sofia ed Emma la dividono in parti uguali. Cento dollari diviso tre fa $33.333 e così via all'infinito, cifra che nessuna carta può pagare.

Un foglio può contenere quel numero infinito. Scrivi =100/3 in tre celle, formattale a due decimali, e ciascuna mostra $33.33. La cella SOMMA mostra $100.00, perché somma le cifre nascoste invece di quelle sullo schermo. Ora un lettore somma le tre celle visibili con una calcolatrice e ottiene $99.99.

Il foglio scrupoloso invece arrotonda: =ROUND(100/3, 2) in ogni cella. Ora ogni cella contiene davvero $33.33, la SOMMA è davvero $99.99, e il centesimo è uscito dal foglio. Lucas deve a Emma $33.33 e Sofia $33.33, quindi il foglio dice che lei riceve indietro $66.66. La sua quota doveva essere $33.33, ma lei ha pagato $33.34 della cena senza che nessuno lo scrivesse.

Una cena da $100.00, pagata da Emma, divisa in tre: due fogli di calcolo e due conti Dimesum
Dove è stata divisaQuota di EmmaQuota di LucasQuota di SofiaLe quote dannoA Emma spettano
Dimesum, un conto il cui hash dà a Emma il centesimo dispari$33.34$33.33$33.33$100.00$66.66
Dimesum, un conto il cui hash dà a Lucas il centesimo dispari$33.33$33.34$33.33$100.00$66.67
Foglio, =100/3 mostrato a due decimali$33.33$33.33$33.33$100.00 nella SOMMA, $99.99 sullo schermo$66.67 sullo schermo
Foglio, =ROUND(100/3, 2)$33.33$33.33$33.33$99.99$66.66

Ogni riga è aritmetica che puoi rifare.

Nella seconda riga di Dimesum, Lucas deve $33.34 e Sofia deve $33.33, e $33.34 più $33.33 fa $66.67. Nel foglio arrotondato, $33.33 più $33.33 fa $66.66. Nessuno dei due è un bug. Sono due regole diverse su un centesimo, e solo una delle due tiene il centesimo nella registrazione.

Perché ogni quota viene prima arrotondata per difetto

Dimesum divide con il metodo del resto più alto, una regola che alcuni parlamenti usano per trasformare le percentuali di voto in seggi interi. Ogni importo è salvato come numero intero dell'unità più piccola della valuta, quindi $100.00 sono 10,000 centesimi. La quota esatta di ciascuno si calcola come frazione, poi tutti ricevono i centesimi interi sotto di essa: 3,333 ciascuno, cioè 9,999.

Resta un centesimo. I centesimi avanzati vengono distribuiti uno alla volta, alle persone le cui frazioni sono state tagliate di più. In una divisione in parti uguali la frazione di tutti è la stessa, un terzo di centesimo, quindi la regola ha bisogno di un criterio di spareggio. Quel criterio di spareggio è il punto in cui la nostra prima versione sbagliava.

La garanzia che il metodo dà è quella che un foglio non può dare: le quote tornano esattamente al totale, e nessuna quota è più lontana di un centesimo dal suo valore esatto. La stessa aritmetica vale per una divisione in parti uguali, una divisione in percentuale, quote ponderate, ogni riga di un conto dettagliato e ogni gruppo di tasse o mance su di esso. Il nostro articolo sulle app per dividere il conto per voce lo mostra su una cena di quattro persone con uno sconto.

Cosa abbiamo provato prima: il membro più anziano prendeva ogni centesimo dispari

Il primo criterio di spareggio era quello ovvio. I membri sono ordinati in base a quando si sono uniti, quindi gli spareggi andavano al membro più anziano. È deterministico, è facile da testare, e su un singolo conto nessuno potrebbe definirlo ingiusto.

Nell'arco di un anno è un sovrapprezzo. Una casa con tre persone divide affitto, luce, internet e spesa, e molti di quei conti lasciano un centesimo in più. Ognuno di quei centesimi andava alla stessa persona, quella che aveva creato il gruppo. Un centesimo non è nulla; qualche centinaio tutti nella stessa direzione sono uno schema che prima o poi qualcuno nota in un foglio.

La risposta del fondatore il 21 agosto 2026 è stata che a farsene carico dovesse essere un partecipante a caso, così da bilanciarsi su molti conti. Il caso aveva un problema per noi. Dimesum ricalcola la divisione di un conto ogni volta che viene modificato, e una modifica viene registrata come nuova voce che riformula la divisione, come descritto in perché una modifica deve riformulare la sua divisione. Con un vero sorteggio casuale, una modifica che cambiasse solo il nome del conto rifarebbe il sorteggio, sposterebbe il centesimo su qualcun altro e registrerebbe una correzione per soldi che non si sono mai mossi.

La soluzione: far ruotare il centesimo dispari con un hash fisso del conto

Così il caso è diventato pseudocasuale e fisso. Ogni conto ha il suo id, e lo passiamo per FNV-1a, un piccolo hash che dà la stessa risposta su ogni macchina e ogni build. L'hash sceglie da quale punto dell'elenco ordinato partono i centesimi avanzati. Stesso conto, stessa risposta, ogni volta che viene calcolato; su molti conti, il punto di partenza cade su ciascuna persona più o meno in egual misura.

L'elenco ordinato resta quello del resto più alto, con gli spareggi risolti a favore del membro più anziano. L'hash sposta solo il punto da cui inizia la distribuzione. In una divisione in tre in parti uguali, significa che ogni conto sceglie una delle tre persone per farsi carico di $33.34, e quella scelta non cambia mai per quel conto.

È per questo che il tuo foglio e l'app non coincidono in modi diversi su conti diversi. Su una cena da $100.00 l'hash dà a Emma il centesimo e i due concordano che le spettano $66.66. Sulla successiva, lo dà a Lucas e l'app dice $66.67. Un foglio con una sola regola per ogni riga non può riprodurlo, a meno che non copi l'hash.

Il costo che abbiamo accettato

Due conti con contenuto identico possono ora differire di un centesimo. Due cene da $100.00 con le stesse tre persone possono dividersi con $33.34 per Emma in una e $33.34 per Sofia nell'altra. Due dei nostri test end to end confrontavano le quote di un conto con quelle di un altro e si sono rotti il giorno in cui questo è uscito; ora verificano il risultato della regola.

Pensiamo che sia lo scambio giusto. Il registro sotto ogni saldo è append-only, quindi un centesimo che si sposta senza motivo verrebbe scritto per sempre; il progetto è descritto in il registro append-only dietro ogni divisione. Un centesimo fisso per ogni conto e distribuito tra le persone non ha mai bisogno di una correzione.

Una colonna che somma dollari ed euro non è un totale

La seconda differenza è più grande di un centesimo ed è sempre colpa del foglio. In viaggio, Emma paga una notte d'albergo da €90 e un biglietto per il museo da $60, e il foglio ha una sola colonna Importo con una SOMMA in fondo. Dice 150. Quel numero non ha valuta, quindi nessuno può doverlo.

Dimesum tiene ogni saldo per valuta e non somma mai tra di esse. Il gruppo vede quanto è dovuto in euro e, separatamente, quanto è dovuto in dollari. Se il gruppo concorda un tasso, Dimesum può mostrare i saldi accorpati in una sola valuta, con il tasso indicato accanto, e il debito stesso resta nella valuta in cui è stato speso.

I bug che nascono dal fare diversamente sono in i bug di denaro causati da una seconda valuta. Se è un viaggio il motivo del confronto, le app per dividere le spese in più valute mette in fila come le altre app gestiscono una seconda valuta.

Accorpare reintroduce un arrotondamento tutto suo. Una conversione arrotonda a centesimi interi, a metà lontano da zero, quindi saldi che in yen davano zero potrebbero dare un centesimo in più in dollari. Lasciamo che il membro con l'id più basso assorba fino a un'unità minima per conversione, e oltre quella soglia il piano di saldo viene rifiutato. Un piano sbagliato in silenzio di $1 è peggio di un errore, perché qualcuno lo pagherebbe.

Lo yen non ha centesimi, e un foglio gliene dà comunque due

La terza differenza compare a ogni viaggio in Giappone. Lo yen non ha un'unità frazionaria: il suo esponente nello standard delle valute ISO 4217 è zero, quindi ¥1 è l'importo più piccolo che chiunque possa pagare. Una cena da ¥10,000 divisa in tre in Dimesum risulta ¥3,334, ¥3,333 e ¥3,333, che sommati danno ¥10,000.

Un foglio formattato per il denaro mostra ¥3,333.33 tre volte, una cifra che nessuna moneta paga. Arrotondalo a yen interi e mostra ¥3,333 tre volte, che sommati danno ¥9,999. Lo yen perde un'unità nello stesso modo in cui il dollaro ha perso un centesimo.

Lo abbiamo rotto noi stessi prima di sistemarlo.

Il codice che legge un importo da una riga di testo una volta lo trasformava in unità minime moltiplicando per 100, cosa giusta per dollari ed euro e sbagliata per gli yen: un taxi da ¥2,000 diventava ¥200,000. Era un errore di 100 volte, e nessuna regola di arrotondamento avrebbe potuto coglierlo.

La conversione ora legge l'esponente di ogni valuta dalla tabella ISO, e una cifra più fine dell'unità più piccola di una valuta viene rifiutata invece che arrotondata. Leggere importi dal testo ha con noi una storia più lunga, raccontata in perché abbiamo eliminato il nostro parser di spese. Come si divide un viaggio in yen senza quel problema è in app per dividere le spese in Giappone.

Cos'altro fa un foglio di calcolo al denaro

Excel memorizza i numeri in virgola mobile binaria, e alcuni decimali non hanno una forma binaria esatta. La nota di Microsoft sull'aritmetica in virgola mobile in Excel spiega perché una somma può risultare di un soffio diversa dalla cifra che ti aspetti. Quasi sempre la visualizzazione lo nasconde, ed è proprio per questo che la cella che vedi e il valore che sommi possono differire.

Anche le funzioni di arrotondamento hanno regole proprie. La funzione ARROTONDA di Excel e ARROTONDA in Fogli Google arrotondano ogni cella per conto suo, senza sapere nulla delle altre celle della divisione. È tutta qui la differenza: una divisione ha bisogno di arrotondare le quote insieme, così che diano ancora il totale del conto.

Dimesum non salva mai il denaro come frazione di un'unità. Ogni importo è un numero intero di centesimi, o di yen, con la sua valuta scritta accanto, e ogni divisione conserva esattamente il suo totale. Se preferisci comunque tenere i soldi del gruppo in un foglio, il nostro modello per tracciare le spese condivise è un buon punto di partenza, e foglio di calcolo o app per le spese condivise spiega dove il foglio smette di bastare.

Come far coincidere il tuo foglio con l'app

Puoi riprodurre a mano i numeri di Dimesum. Lavora in centesimi interi. Dai a ciascuno i centesimi interi sotto la sua quota esatta, conta i centesimi avanzati e distribuiscili uno alla volta.

  1. Converti il conto in centesimi: $100.00 sono 10,000.
  2. Dai a ciascuno la parte intera della sua quota esatta: 3,333 ciascuno, 9,999 in tutto.
  3. Dai il centesimo avanzato alla persona che l'app mostra come quella che se ne fa carico, e controlla che le quote diano 10,000.
  4. Tieni un foglio per valuta, e non mettere mai una SOMMA a cavallo di due.

Il terzo passo è l'unico che non puoi prevedere senza l'hash del conto, quindi leggilo dal conto. L'aritmetica più lunga per qualsiasi divisione, con pesi e percentuali, è in il metodo del calcolatore di spese, e lo stesso controllo applicato all'intero storico di un gruppo è in come tenere traccia di chi deve a chi in viaggio.

Cosa questo ancora non può fare

Non può far coincidere il tuo foglio e l'app su ogni conto senza fatica. Un foglio con una sola regola di arrotondamento per colonna differirà da Dimesum di un centesimo su quasi ogni conto che lascia un resto, e la persona che si fa carico del centesimo cambierà da un conto all'altro. È la regola che funziona.

Non può nemmeno rendere esatto un totale accorpato. Un saldo mostrato in una sola valuta a un tasso concordato è indicativo, e il piano di saldo costruito da esso può sbagliare di un'unità minima per conversione. Il debito che conta resta nella valuta in cui è stato speso, ed è per questo che saldare i conti di un gruppo si fa una valuta alla volta.

Controlla la somma, non ogni cella

Quando l'app e il tuo foglio differiscono di un centesimo, somma le quote sul conto: se danno il totale, il centesimo sta con una persona di proposito. Per vedere quale, apri Dimesum, tocca il conto e leggi la quota che è più grande di un centesimo rispetto alle altre.

Domande frequenti

Perché la mia app per dividere il conto differisce di un centesimo da Excel?

Perché Excel arrotonda ogni quota per conto suo e l'app arrotonda le quote insieme. Un conto da $100.00 diviso in tre fa $33.33 tre volte in un foglio arrotondato, che sommati danno $99.99. Dimesum dà a una persona $33.34 così le quote danno $100.00, e un hash fisso del conto decide chi si fa carico di quel centesimo.

Chi paga il centesimo in più quando un conto si divide in tre?

Una persona, e in Dimesum la decide l'hash del conto stesso. Le quote si calcolano con il metodo del resto più alto, e il punto da cui partono i centesimi avanzati ruota in base a un hash fisso del conto. Lo stesso conto dà sempre la stessa risposta, e su molti conti il centesimo finisce su ciascuna persona più o meno in egual misura.

Perché Dimesum non sceglie una persona a caso per il centesimo dispari?

Perché un vero sorteggio casuale sposterebbe il centesimo ogni volta che un conto viene modificato. Dimesum riformula la divisione a ogni modifica, quindi un nuovo sorteggio registrerebbe una correzione per soldi che non si sono mai mossi. Un hash fisso del conto si comporta come una scelta casuale su molti conti e dà sempre la stessa risposta per un singolo conto.

Posso sommare saldi in due valute nella stessa colonna di un foglio?

No, il totale non significa nulla. €90 e $60 sommati a 150 sono un numero senza valuta, quindi nessuno può doverlo. Dimesum tiene un saldo per valuta e non somma mai tra di esse; un gruppo può vederli accorpati a un tasso che concorda, indicato accanto, mentre ogni debito resta nella valuta in cui è stato speso.

Come divide Dimesum gli yen se non ci sono centesimi?

In yen interi, perché l'unità più piccola dello yen è ¥1. Una cena da ¥10,000 divisa in tre fa ¥3,334, ¥3,333 e ¥3,333, che sommati danno ¥10,000. Un foglio formattato con due decimali mostra ¥3,333.33, che nessuna moneta può pagare, e arrotondare ogni cella a yen interi perde ¥1 nello stesso modo in cui un foglio in dollari perde un centesimo.