HOWTO · JavaScript

Divisione intera in JavaScript

Scegliere Math.trunc o Math.floor in JavaScript per calcolare correttamente quoziente e resto anche con valori negativi.

In questa pagina

JavaScript non ha un operatore // per la divisione intera. Per valori Number ordinari, usare Math.trunc(dividend / divisor) quando il quoziente deve scartare la parte frazionaria verso zero e % per il resto. Scegliere Math.floor() solo se la regola richiesta è l’arrotondamento verso il basso. Con valori negativi le due scelte differiscono, quindi la regola conta più di una scorciatoia.

Risposta diretta: troncamento o arrotondamento per difetto

La divisione intera può indicare due regole. Un quoziente troncato elimina le cifre frazionarie: Math.trunc(-13 / 5) è -2. Il quoziente con floor arrotonda verso meno infinito: Math.floor(-13 / 5) è -3. Per input positivi entrambi danno 2, e la differenza può restare nascosta fino a un valore negativo in produzione.

Usare il troncamento per separare una quantità con segno in quoziente e resto con segno. Usare la divisione floor per bucket con indice zero o indici ciclici, dove il quoziente deve sempre scendere. L’operatore % di JavaScript restituisce un resto, non un modulo matematico sempre non negativo; il suo segno segue il dividendo. MDN distingue resto e modulo matematico.

Quoziente e resto Number consigliati

Con input Number finiti, Math.trunc e % rendono esplicita la relazione tra quoziente e resto. È l’approccio consigliato per una normale divisione intera. Prima del calcolo verificare che il divisore non sia zero: un Number non zero diviso per zero con segno produce Infinity con segno, 0 / 0 è NaN, e anche il resto Number con divisore zero è NaN. La specifica ECMAScript definisce questi casi.

const dividend = 13;
const divisor = 5;

console.log(`quotient: ${Math.trunc(dividend / divisor)}`);
console.log(`remainder: ${dividend % divisor}`);
quotient: 2
remainder: 3

Il resto può verificare il risultato: per input interi, dividend equivale a divisor * quotient + remainder. La relazione è utile per la convalida, ma calcolare il quoziente con Math.trunc comunica la regola di arrotondamento più chiaramente che derivarla in modo indiretto.

Operandi negativi e resto con segno

Gli operandi negativi separano troncamento e semantica floor. Con -13 / 5, il troncamento dà -2 e la divisione floor dà -3. Il risultato di % è -3, perché JavaScript conserva il segno del dividendo per un resto diverso da zero. Nessuna delle operazioni fallisce con input negativi: rispondono a domande diverse.

const dividend = -13;
const divisor = 5;

console.log(`truncating quotient: ${Math.trunc(dividend / divisor)}`);
console.log(`floor quotient: ${Math.floor(dividend / divisor)}`);
console.log(`remainder: ${dividend % divisor}`);
truncating quotient: -2
floor quotient: -3
remainder: -3

Quando servono divisione floor o modulo

Se l’applicazione richiede un modulo non negativo per un divisore positivo, normalizzare il resto invece di supporre che % lo faccia già. Abbinarlo a Math.floor affinché entrambi i valori usino la stessa convenzione floor. L’esempio vale per un ciclo di cinque elementi, non per ogni attività con quoziente e resto.

const dividend = -13;
const divisor = 5;
const quotient = Math.floor(dividend / divisor);
const modulo = ((dividend % divisor) + divisor) % divisor;

console.log(`floor quotient: ${quotient}`);
console.log(`non-negative modulo: ${modulo}`);
floor quotient: -3
non-negative modulo: 2

Questa normalizzazione presume un divisore positivo. Definire e testare separatamente la convenzione desiderata se il divisore può essere negativo.

Interi grandi esatti con BigInt

Number usa valori a virgola mobile IEEE-754. Non rappresenta esattamente ogni intero oltre l’intervallo sicuro; validare quindi gli input con Number.isSafeInteger prima di affidarsi a un quoziente o resto Number. Per interi esatti più grandi, usare coerentemente BigInt. La divisione BigInt tronca verso zero e il resto segue la stessa idea di segno.

const dividend = 13n;
const divisor = 5n;

console.log(`quotient: ${dividend / divisor}`);
console.log(`remainder: ${dividend % divisor}`);

try {
  13n / 0n;
} catch (error) {
  console.log(`zero divisor: ${error.name}`);
}

try {
  13n / 5;
} catch (error) {
  console.log(`mixed types: ${error.name}`);
}
quotient: 2
remainder: 3
zero divisor: RangeError
mixed types: TypeError

Non mescolare operandi Number e BigInt: convertire deliberatamente prima dell’aritmetica. Un divisore zero BigInt genera RangeError, diversamente da un divisore zero Number, quindi la validazione dell’input è utile in entrambi i casi. MDN documenta divisione BigInt, errori di tipi misti e divisore zero.

Perché non usare coercizione bitwise o parseInt

Si possono vedere ~~value o value | 0 come idiomi compatti di troncamento. Evitarli per la divisione intera generale: gli operatori bitwise convertono a un intero con segno a 32 bit e modificano i valori fuori intervallo. parseInt serve ad analizzare stringhe, non è un’API di arrotondamento numerico. MDN documenta Math.trunc e la differenza dalla conversione bitwise. Il confronto mostra il limite dei 32 bit e la corretta analisi di una stringa.

const value = 2 ** 32 + 1;

console.log(`Math.trunc: ${Math.trunc(value)}`);
console.log(`~~value: ${~~value}`);
console.log(`value | 0: ${value | 0}`);
console.log(`parseInt("13.8", 10): ${parseInt("13.8", 10)}`);
Math.trunc: 4294967297
~~value: 1
value | 0: 1
parseInt("13.8", 10): 13

Usare Math.trunc per un valore Number numerico e parseInt(text, 10) solo quando l’input è testo da analizzare. Nessuna scorciatoia risolve la precisione in virgola mobile; usare BigInt quando occorre aritmetica esatta su grandi interi.

Riepilogo decisionale e limiti

Usare Math.trunc(a / b) e a % b per la normale divisione intera JavaScript. Usare Math.floor(a / b) con modulo normalizzato solo se serve la semantica floor. Usare BigInt per grandi interi esatti, rifiutare un divisore zero e non mescolare mai BigInt con Number nella stessa operazione. Evitare coercizione bitwise e parseInt come alternative generiche, perché risolvono problemi diversi.