Risposte:
Stai facendo 157/32che sta dividendo due numeri interi tra loro, il che si traduce sempre in un numero intero arrotondato per difetto. Quindi (int) Math.ceil(...)non sta facendo nulla. Ci sono tre possibili soluzioni per ottenere ciò che desideri. Mi raccomando utilizzando l'opzione 1 o l'opzione 2 . Si prega di NON utilizzare l' opzione 0 .
## Opzione 0
Converti ae bin doppio e puoi usare la divisione e Math.ceilcome volevi che funzionasse. Tuttavia, sconsiglio vivamente l'uso di questo approccio, perché la doppia divisione può essere imprecisa. Per saperne di più sull'imprecisione dei doppi vedi questa domanda .
int n = (int) Math.ceil((double) a / b));
##Opzione 1
int n = a / b + ((a % b == 0) ? 0 : 1);
Fai a / bsempre floor se ae bsono entrambi numeri interi. Quindi hai un'istruzione if in linea che controlla se dovresti o meno soffermarti invece di floor. Quindi +1 o +0, se c'è un resto con la divisione hai bisogno di +1. a % b == 0controlla il resto.
##Opzione 2
Questa opzione è molto breve, ma forse per alcuni meno intuitiva. Penso che questo approccio meno intuitivo sarebbe più veloce dell'approccio a doppia divisione e confronto:
tieni presente che questo non funziona per b < 0.
int n = (a + b - 1) / b;
Per ridurre la possibilità di overflow è possibile utilizzare quanto segue. Tuttavia, tieni presente che non funziona per a = 0e b < 1.
int n = (a - 1) / b + 1;
## Spiegazione dietro l '"approccio meno intuitivo"
Dal momento che la divisione di due interi in Java (e nella maggior parte degli altri linguaggi di programmazione) darà sempre il risultato finale. Così:
int a, b;
int result = a/b (is the same as floor(a/b) )
Ma non vogliamo floor(a/b), ma ceil(a/b), e usando le definizioni e le trame di Wikipedia :
Con queste trame della funzione pavimento e soffitto puoi vedere la relazione.

Lo puoi vedere floor(x) <= ceil(x). Abbiamo bisogno floor(x + s) = ceil(x). Quindi dobbiamo trovare s. Se lo prendiamo 1/2 <= s < 1sarà giusto (prova alcuni numeri e vedrai che lo fa, trovo difficile dimostrarlo). E 1/2 <= (b-1) / b < 1così
ceil(a/b) = floor(a/b + s)
= floor(a/b + (b-1)/b)
= floor( (a+b-1)/b) )
Questa non è una vera prova, ma spero che tu ne sia soddisfatto. Se qualcuno può spiegarlo meglio lo apprezzerei anch'io. Magari chiedilo su MathOverflow .
157/32 è int/int, il che si traduce in un file int.
Provare a utilizzare il doppio letterale - 157/32d, che è int/double, che si traduce in una double.
157/32è una divisione intera perché tutti i letterali numerici sono numeri interi se non diversamente specificato con un suffisso ( dper double lper long)
la divisione viene arrotondata per difetto (a 4) prima di essere convertita in un doppio (4.0) che viene quindi arrotondato per eccesso (a 4.0)
se usi una variabile puoi evitarlo
double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
Nessuno ha menzionato il più intuitivo:
int x = (int) Math.round(Math.ceil((double) 157 / 32));
Questa soluzione corregge l' imprecisione della doppia divisione.
In Java l'aggiunta di uno .0 lo renderà un doppio ...
int total = (int) Math.ceil(157.0 / 32.0);
Quando si dividono due numeri interi, ad es.
int c = (int) a / (int) b;
il risultato è un int, il cui valore è adiviso per b, arrotondato verso zero. Poiché il risultato è già arrotondato, ceil()non fa nulla. Nota che questo arrotondamento non è lo stesso di floor(), che arrotonda verso l'infinito negativo. Quindi, è 3/2uguale 1(ed è floor(1.5)uguale 1.0, ma è (-3)/2uguale -1(ma è floor(-1.5)uguale -2.0).
Questo è importante perché, se a/bfosse sempre la stessa floor(a / (double) b), allora si può solo implementare ceil()di a/bcome -( (-a) / b).
Il suggerimento di andare ceil(a/b)da
int n = (a + b - 1) / b;, che è equivalente a a / b + (b - 1) / b, o(a - 1) / b + 1
funziona perché ceil(a/b)è sempre maggiore di uno floor(a/b), tranne quando a/bè un numero intero. Quindi, vuoi spostarlo al (o oltre) il numero intero successivo, a meno che non a/bsia un numero intero. L'aggiunta 1 - 1 / bfarà questo. Per i numeri interi, non li spingerà fino al numero intero successivo. Per tutto il resto, lo farà.
Yikes. Si spera che abbia senso. Sono sicuro che ci sia un modo matematicamente più elegante per spiegarlo.
Inoltre per convertire un numero da intero a numero reale puoi aggiungere un punto:
int total = (int) Math.ceil(157/32.);
E anche il risultato di (157/32.) Sarà reale. ;)
int total = (int) Math.ceil( (double)157/ (double) 32);
Java fornisce solo la divisione dei piani /per impostazione predefinita. Ma possiamo scrivere soffitto in termini di pavimento . Vediamo:
Qualsiasi numero intero ypuò essere scritto con il modulo y == q*k+r. Secondo la definizione di divisione del pavimento (qui floor) che completa r,
floor(q*k+r, k) == q , where 0 ≤ r ≤ k-1
e della divisione del soffitto (qui ceil) che arrotonda r₁,
ceil(q*k+r₁, k) == q+1 , where 1 ≤ r₁ ≤ k
dove possiamo sostituire r+1per r₁:
ceil(q*k+r+1, k) == q+1 , where 0 ≤ r ≤ k-1
Quindi sostituiamo la prima equazione con la terza per qottenere
ceil(q*k+r+1, k) == floor(q*k+r, k) + 1 , where 0 ≤ r ≤ k-1
Infine, data qualsiasi numero intero yin cui y = q*k+r+1per alcuni q, k, r, abbiamo
ceil(y, k) == floor(y-1, k) + 1
E abbiamo finito. Spero che questo ti aiuti.
ceilè chiaro il motivo per cui è definito come tale dalla definizione intuitiva, in particolare dove stiamo prendendo il limite di un intero, cioè r1 = k. Poiché i casi limite sono ciò che è complicato in questo, penso che debba essere spiegato un po 'di più.
Ci sono due metodi con cui puoi arrotondare il tuo doppio valore.
Se vuoi la tua risposta 4.90625 come 4 allora dovresti usare Math.floor e se vuoi la tua risposta 4.90625 come 5 allora puoi usare Math.ceil
Puoi fare riferimento al seguente codice per questo.
public class TestClass {
public static void main(String[] args) {
int floorValue = (int) Math.floor((double)157 / 32);
int ceilValue = (int) Math.ceil((double)157 / 32);
System.out.println("Floor: "+floorValue);
System.out.println("Ceil: "+ceilValue);
}
}
int total = (157-1)/32 + 1
o più generale
(a-1)/b +1