127 votes

Arrondir à un entier avec Math.ceil en Java

int total = (int) Math.ceil(157/32);

Pourquoi est-ce que ça donne toujours 4 ? 157/32 = 4.90625 J'ai regardé autour de moi et cela semble être la bonne méthode.

J'ai essayé total comme double type, mais obtenir 4.0.

Qu'est-ce que je fais de mal ?

241voto

martijnn2008 Points 481

Vous faites 157/32 qui consiste à diviser deux entiers l'un par l'autre, ce qui donne toujours un entier arrondi vers le bas. Par conséquent, le (int) Math.ceil(...) ne fait rien. Il y a trois solutions possibles pour obtenir ce que vous voulez. I recommander en utilisant soit option 1 o option 2 . S'il vous plaît, faites PAS utiliser option 0 .

Option 0

Convertir a y b en un double, et vous pouvez utiliser la division et le Math.ceil comme vous vouliez qu'il fonctionne. Cependant, je déconseille fortement l'utilisation de cette approche, car la double division peut être imprécise. Pour en savoir plus sur l'imprécision des doubles, voir cette question .

int n = (int) Math.ceil((double) a / b));

Option 1

int n = a / b + ((a % b == 0) ? 0 : 1); 

Tu le fais. a / b avec toujours un plancher si a y b sont tous deux des entiers. Ensuite, vous avez une instruction if en ligne qui vérifie si vous devez ou non utiliser ceil au lieu de floor. Donc +1 ou +0, s'il y a un reste avec la division, il faut +1. a % b == 0 des chèques pour le reste.

Option 2

Cette option est très courte, mais peut-être pour certains moins intuitive. Je pense que cette approche moins intuitive serait plus rapide que l'approche par double division et comparaison :
Veuillez noter que cela ne fonctionne pas pour b < 0 .

int n = (a + b - 1) / b;

Pour réduire les risques de débordement, vous pouvez utiliser la méthode suivante. Cependant, notez que cela ne fonctionne pas pour les fichiers a = 0 y b < 1 .

int n = (a - 1) / b + 1;

Explication de l'"approche moins intuitive".

Étant donné que la division de deux nombres entiers en Java (et dans la plupart des autres langages de programmation) donne toujours un résultat plancher. Donc :

int a, b;
int result = a/b (is the same as floor(a/b) )

Mais nous ne voulons pas floor(a/b) mais ceil(a/b) et en utilisant les définitions et les graphiques de Wikipedia : enter image description here

Avec ces tracés de la fonction plancher et plafond, vous pouvez voir la relation.

Floor functionCeil function

Vous pouvez voir que floor(x) <= ceil(x) . Nous avons besoin floor(x + s) = ceil(x) . Nous devons donc trouver s . Si nous prenons 1/2 <= s < 1 il sera juste (essayez quelques chiffres et vous verrez que c'est le cas, j'ai moi-même du mal à le prouver). Et 1/2 <= (b-1) / b < 1 donc

ceil(a/b) = floor(a/b + s)
          = floor(a/b + (b-1)/b)
          = floor( (a+b-1)/b) )

Ce n'est pas une preuve réelle, mais j'espère que vous en êtes satisfait. Si quelqu'un peut mieux l'expliquer, je l'apprécierais aussi. Demandez-le peut-être sur MathOverflow .

62voto

Bozho Points 273663

157/32 est int/int ce qui donne lieu à une int .

Essayez d'utiliser le double littéral - 157/32d qui est int/double ce qui donne lieu à une double .

0 votes

Etes-vous sûr que int/int donnera toujours un int ?! pouvez-vous s'il vous plaît donner la source de cela ?!

6 votes

37voto

ratchet freak Points 22412

157/32 est une division entière car tous les littéraux numériques sont des entiers, sauf indication contraire avec un suffixe ( d pour le double l pour longtemps)

la division est arrondie vers le bas (à 4) avant d'être convertie en un double (4.0) qui est ensuite arrondi vers le haut (à 4.0).

si vous utilisez une variable, vous pouvez éviter cela

double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);

27voto

Phoebus Points 194
int total = (int) Math.ceil((double)157/32);

12voto

I.G. Pascual Points 1428

Personne n'a mentionné le plus intuitif :

int x = (int) Math.round(Math.ceil((double) 157 / 32));

Cette solution corrige le double l'imprécision de la division.

1 votes

Math.round renvoie un long

0 votes

Merci @ZulqurnainJutt, j'ai ajouté un casting.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X