---
title: "Aritmetica del denaro in centesimi interi, e lo sconto che è sparito"
description: "Abbiamo applicato uno sconto di cinquanta centesimi e la contabilità non ne ha registrato nemmeno uno. La virgola mobile non c'entrava niente. Guida pratica ai conti sul denaro con i numeri interi: limiti, ripartizione e come far quadrare al centesimo una contabilità di prezzi unitari."
url: "https://bookatu.com/it-it/blog/money-math-in-integer-cents"
language: "it"
section: "Blog"
category: "Tecnica"
author: "Il team tecnico di Bookatu"
published: "2026-07-13"
updated: "2026-07-13"
tags: ["denaro in centesimi", "virgola mobile e valute", "ripartizione dello sconto", "errori di arrotondamento", "sviluppo dei pagamenti"]
---

# Aritmetica del denaro in centesimi interi, e lo sconto che è sparito

Abbiamo applicato uno sconto di cinquanta centesimi e la contabilità non ne ha registrato nemmeno uno. La virgola mobile non c'entrava niente. Guida pratica ai conti sul denaro con i numeri interi: limiti, ripartizione e come far quadrare al centesimo una contabilità di prezzi unitari.

> **In breve**
>
> - Salva e calcola il denaro in centesimi interi. I numeri in virgola mobile sono il bug famoso, la vera insidia è la politica di arrotondamento.
> - Uno sconto ripartito deve quadrare: dopo aver arrotondato la quota di ogni riga, spingi i centesimi avanzati sulle righe che hanno spazio finché la somma non è esatta.
> - Se la contabilità salva un prezzo unitario per riga, un totale scontato che non si divide in modo esatto non è rappresentabile. Spezza la riga in due prezzi distanti un centesimo.
> - Metti un limite a ogni estremo: gli sconti al subtotale, le quantità alla giacenza, i totali a zero.

Ogni sviluppatore impara presto che 0.1 più 0.2 non fa 0.3, quindi salviamo tutti il denaro in centesimi interi e ci sentiamo al sicuro. Poi costruisci qualcosa di vero, per esempio uno sconto in percentuale su un carrello, e scopri che gli interi risolvono solo il primo problema. Il secondo è che alla divisione della tua contabilità non importa niente.

## I cinquanta centesimi spariti

Ecco la situazione che ci ha morso, ridotta all'osso. Un carrello contiene 100 unità di un articolo da un dollaro. Il cliente ha cinquanta centesimi di sconto sull'ordine. Il subtotale è 10.000 centesimi, lo sconto è 50 centesimi e il totale scontato è 9.950 centesimi. Fin qui solo numeri interi.

Adesso registra quella vendita in una contabilità che salva un prezzo unitario per riga, come piace ai sistemi contabili. Il prezzo unitario scontato è 9.950 diviso 100, cioè 99,5 centesimi. Non è un numero intero, quindi viene arrotondato a 100. Adesso la contabilità dice 100 unità a 100 centesimi: una vendita a prezzo pieno. Lo sconto non si è ridotto. È sparito, mentre l'interfaccia prometteva al cliente 9.950 e i libri dicevano 10.000.

```js
// The trap: one rounded unit price cannot represent every total.
const subtotal = 100 * 100;              // 10000c
const discounted = subtotal - 50;        // 9950c
const unit = Math.round(discounted / 100); // 100c ... the discount is gone
console.log(unit * 100);                 // 10000c, not 9950c

// The fix: split the line into two prices one cent apart.
const qty = 100;
const base = Math.floor(discounted / qty);   // 99c
const rem = discounted - base * qty;         // 50 units get one extra cent
// rem units at (base + 1), the rest at base:
// 50 * 100 + 50 * 99 === 9950  ✓ exact, and every price is an integer
```

Spezzare la riga sembra una pignoleria finché non vedi cosa ti compra. Cinquanta unità a 100 centesimi più cinquanta unità a 99 centesimi fa esattamente 9.950. Ogni riga salva ancora un prezzo unitario intero e onesto, le quantità tornano ancora, e la somma della contabilità corrisponde al centesimo al numero sullo scontrino. Niente di tutto questo è possibile con un unico prezzo arrotondato.

## La ripartizione ha bisogno di un passaggio di riconciliazione

La stessa malattia ricompare un livello più su, quando uno sconto sull'ordine si distribuisce su più righe. Dai a ogni riga la sua quota proporzionale e arrotonda, e le quote sommeranno a quasi lo sconto. A volte un centesimo in più, a volte uno in meno, ogni tanto esatte, che è il risultato peggiore di tutti perché nasconde il bug a un test superficiale.

```js
// Prorate by share, then push the rounding leftover onto lines with room.
let allocated = 0;
for (const line of lines) {
  line.discount = Math.min(
    line.subtotal,
    Math.round((discount * line.subtotal) / orderSubtotal),
  );
  allocated += line.discount;
}
let remainder = discount - allocated; // may be negative
for (const line of lines) {
  if (remainder === 0) break;
  const room = remainder > 0 ? line.subtotal - line.discount : line.discount;
  const move = Math.min(Math.abs(remainder), room) * Math.sign(remainder);
  line.discount += move;
  remainder -= move;
}
// invariant: sum(line.discount) === discount, and no line goes negative
```

Due dettagli di quel ciclo se li sono guadagnati nel modo duro. Il resto si distribuisce su qualsiasi riga abbia capienza, non solo sull'ultima, perché l'ultima riga può essere un articolo da sei centesimi senza spazio per assorbire tre centesimi avanzati. E ogni quota è limitata al subtotale della sua riga, perché uno sconto più grande della riga implica un prezzo unitario negativo, ed è così che una contabilità comincia a mentire nell'altra direzione.

![Una schermata del punto vendita con un subtotale, uno sconto del dieci per cento e il totale scontato esatto](https://bookatu.com/blog/shots/pos-discount-light.png)

*Lo scontrino noioso è tutto il punto: subtotale, sconto e un totale che la contabilità riproduce al centesimo.*

## Metti un limite a ogni estremo

- Gli sconti si limitano all'intervallo tra zero e il subtotale. Un centodieci per cento di sconto è un errore di battitura, non un rimborso.
- Interpreta con prudenza gli importi digitati dall'utente: vuoto e non numerico valgono zero, mai NaN in mezzo a un calcolo.
- Le quantità si limitano a quello che esiste. Il codice che gestisce il denaro eredita ogni bug di magazzino che sta a monte.
- Prova i totali che non si dividono in modo esatto. Tre articoli da dieci dollari con un dollaro di sconto è un test migliore di qualsiasi numero tondo.

Niente di tutto questo è affascinante, ed è esattamente per questo che sfugge alla revisione. L'aritmetica sembra corretta perché è corretta, fino al momento in cui la divisione intera butta via in silenzio un resto che qualcuno doveva ricevere. Scrivi l'invariante, la somma delle parti è uguale al tutto, e metti un test a fare da guardia.

> Gli interi tengono onesto il denaro. La riconciliazione tiene onesti gli interi.
